From d07d34c3c95f39f2cee88da5023ef5a3fcef6850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciar=C3=A1n=20Curley?= Date: Tue, 20 Oct 2026 16:38:58 +0100 Subject: [PATCH 1/4] chore: enable jsdoc formatting in oxfmt and reformat Co-Authored-By: Claude Sonnet 5.5 --- .../react/plugins/broadcastQueryClient.md | 20 +- .../plugins/createAsyncStoragePersister.md | 8 +- .../react/plugins/createPersister.md | 29 +- .../plugins/createSyncStoragePersister.md | 10 +- .../react/plugins/persistQueryClient.md | 34 +- docs/framework/vue/plugins/createPersister.md | 29 +- .../app/interceptor/mock-api.interceptor.ts | 9 +- .../src/app/services/tasks.service.ts | 12 +- .../app/interceptor/mock-api.interceptor.ts | 9 +- .../src/app/services/tasks.service.ts | 8 +- .../react/offline/public/mockServiceWorker.js | 16 +- .../solid/offline/public/mockServiceWorker.js | 16 +- .../src/components/query-boundary.tsx | 21 +- .../react-next-15/app/make-query-client.ts | 4 +- .../react-next-16/app/make-query-client.ts | 4 +- oxfmt.config.ts | 1 + oxlint.config.ts | 24 +- .../scripts/prepack.js | 20 +- .../src/__tests__/inject-query.test-d.ts | 3 - .../src/__tests__/test-utils.ts | 1 + .../src/create-base-query.ts | 20 +- .../devtools-panel/inject-devtools-panel.ts | 8 +- .../src/devtools-panel/stub.ts | 4 +- .../src/devtools-panel/types.ts | 47 +- .../src/devtools/stub.ts | 4 +- .../src/devtools/types.ts | 79 +- .../src/devtools/with-devtools.ts | 20 +- .../src/infinite-query-options.ts | 296 +-- .../src/inject-infinite-query.ts | 328 ++-- .../src/inject-is-fetching.ts | 61 +- .../src/inject-is-mutating.ts | 39 +- .../src/inject-is-restoring.ts | 31 +- .../src/inject-mutation-state.ts | 101 +- .../src/inject-mutation.ts | 211 ++- .../src/inject-queries.ts | 266 +-- .../src/inject-query-client.ts | 6 +- .../src/inject-query.ts | 202 ++- .../src/mutation-options.ts | 97 +- .../src/pending-tasks-compat.ts | 5 +- .../src/providers.ts | 158 +- .../src/query-options.ts | 275 +-- .../src/signal-proxy.ts | 11 +- .../angular-query-experimental/src/types.ts | 217 ++- .../src/with-persist-query-client.ts | 14 +- packages/eslint-plugin-query/src/index.ts | 13 +- .../exhaustive-deps/exhaustive-deps.rule.ts | 15 +- .../exhaustive-deps/exhaustive-deps.utils.ts | 59 +- .../constants.ts | 6 +- .../mutation-property-order/constants.ts | 7 +- .../no-rest-destructuring.utils.ts | 7 +- .../no-unstable-deps/no-unstable-deps.rule.ts | 49 +- .../no-void-query-fn/no-void-query-fn.rule.ts | 8 +- .../prefer-query-options.rule.ts | 43 +- packages/eslint-plugin-query/src/types.ts | 9 +- .../src/utils/create-property-order-rule.ts | 16 +- .../src/utils/detect-react-query-imports.ts | 8 +- .../src/utils/get-docs-url.ts | 1 + .../src/utils/sort-data-by-order.ts | 9 +- .../src/utils/unique-by.ts | 1 + packages/lit-query/src/QueryClientProvider.ts | 71 +- packages/lit-query/src/accessor.ts | 33 +- packages/lit-query/src/context.ts | 29 +- .../src/controllers/BaseController.ts | 29 +- .../src/createInfiniteQueryController.ts | 58 +- .../lit-query/src/createMutationController.ts | 55 +- .../lit-query/src/createQueriesController.ts | 69 +- .../lit-query/src/createQueryController.ts | 51 +- .../lit-query/src/infiniteQueryOptions.ts | 24 +- packages/lit-query/src/mutationOptions.ts | 20 +- .../src/queryObserverResultTracker.ts | 9 +- packages/lit-query/src/queryOptions.ts | 36 +- packages/lit-query/src/types.ts | 24 +- packages/lit-query/src/useIsFetching.ts | 36 +- packages/lit-query/src/useIsMutating.ts | 36 +- packages/lit-query/src/useMutationState.ts | 46 +- .../src/PreactQueryDevtools.tsx | 37 +- .../src/PreactQueryDevtoolsPanel.tsx | 33 +- packages/preact-query-devtools/src/index.ts | 3 +- .../src/PersistQueryClientProvider.tsx | 21 +- .../preact-query/src/HydrationBoundary.tsx | 85 +- .../preact-query/src/IsRestoringProvider.ts | 15 +- .../preact-query/src/QueryClientProvider.tsx | 53 +- .../src/QueryErrorResetBoundary.tsx | 162 +- .../__tests__/ErrorBoundary/ErrorBoundary.ts | 5 +- .../src/__tests__/ErrorBoundary/index.ts | 6 +- .../src/__tests__/useSuspenseQuery.test.tsx | 8 +- .../preact-query/src/errorBoundaryUtils.ts | 34 +- .../preact-query/src/infiniteQueryOptions.ts | 257 +-- packages/preact-query/src/mutationOptions.ts | 81 +- packages/preact-query/src/queryOptions.ts | 228 ++- packages/preact-query/src/suspense.ts | 26 +- packages/preact-query/src/types.ts | 277 +-- packages/preact-query/src/useBaseQuery.ts | 20 +- packages/preact-query/src/useInfiniteQuery.ts | 440 ++--- packages/preact-query/src/useIsFetching.ts | 48 +- packages/preact-query/src/useMutation.ts | 249 +-- packages/preact-query/src/useMutationState.ts | 127 +- .../src/usePrefetchInfiniteQuery.tsx | 77 +- .../preact-query/src/usePrefetchQuery.tsx | 58 +- packages/preact-query/src/useQueries.ts | 189 +- packages/preact-query/src/useQuery.ts | 363 ++-- .../src/useSuspenseInfiniteQuery.ts | 157 +- .../preact-query/src/useSuspenseQueries.ts | 578 +++--- packages/preact-query/src/useSuspenseQuery.ts | 120 +- packages/preact-query/src/utils.ts | 30 +- .../src/asyncThrottle.ts | 10 +- .../src/index.ts | 31 +- .../src/utils.ts | 4 +- .../src/index.ts | 37 +- packages/query-codemods/src/utils/index.cjs | 5 +- .../transformers/query-cache-transformer.cjs | 10 +- .../transformers/query-client-transformer.cjs | 4 +- .../src/v4/key-transformation.cjs | 4 +- .../src/v5/is-loading/is-loading.cjs | 15 +- .../keep-previous-data/keep-previous-data.cjs | 13 +- .../filter-aware-usage-transformer.cjs | 42 +- .../query-fn-aware-usage-transformer.cjs | 6 +- .../src/v5/remove-overloads/utils/index.cjs | 17 +- .../utils/unknown-usage-error.cjs | 1 - .../src/v5/rename-hydrate/rename-hydrate.cjs | 5 +- packages/query-core/src/environmentManager.ts | 36 +- packages/query-core/src/focusManager.ts | 82 +- packages/query-core/src/hydration.ts | 203 ++- .../query-core/src/infiniteQueryBehavior.ts | 34 +- .../query-core/src/infiniteQueryObserver.ts | 104 +- packages/query-core/src/mutation.ts | 123 +- packages/query-core/src/mutationCache.ts | 167 +- packages/query-core/src/mutationObserver.ts | 110 +- packages/query-core/src/notifyManager.ts | 86 +- packages/query-core/src/onlineManager.ts | 63 +- packages/query-core/src/queriesObserver.ts | 114 +- packages/query-core/src/query.ts | 310 ++-- packages/query-core/src/queryCache.ts | 251 +-- packages/query-core/src/queryClient.ts | 785 ++++---- packages/query-core/src/queryObserver.ts | 237 ++- packages/query-core/src/removable.ts | 30 +- packages/query-core/src/retryer.ts | 91 +- packages/query-core/src/streamedQuery.ts | 47 +- packages/query-core/src/subscribable.ts | 44 +- packages/query-core/src/timeoutManager.ts | 161 +- packages/query-core/src/types.ts | 1590 +++++++---------- packages/query-core/src/utils.ts | 360 ++-- packages/query-devtools/src/Devtools.tsx | 17 +- packages/query-devtools/src/Explorer.tsx | 19 +- .../src/TanstackQueryDevtools.tsx | 14 +- .../src/TanstackQueryDevtoolsPanel.tsx | 17 +- .../src/contexts/DevtoolsOfflineContext.ts | 1 + .../src/contexts/DevtoolsStateContext.ts | 4 +- .../contexts/DevtoolsSubscriptionsContext.ts | 4 +- .../src/contexts/PiPContext.tsx | 14 +- .../src/contexts/QueryDevtoolsContext.ts | 4 +- .../src/contexts/ThemeContext.ts | 4 +- packages/query-devtools/src/contexts/types.ts | 122 +- .../src/createCacheSubscriptionRegistry.ts | 14 +- packages/query-devtools/src/icons/index.tsx | 28 +- .../src/providers/DevtoolsOfflineProvider.tsx | 5 +- .../src/providers/DevtoolsStateProvider.tsx | 1 + .../DevtoolsSubscriptionsProvider.tsx | 4 +- packages/query-devtools/src/utils.tsx | 41 +- .../src/createPersister.ts | 155 +- .../query-persist-client-core/src/persist.ts | 108 +- .../src/retryStrategies.ts | 12 +- .../query-sync-storage-persister/src/index.ts | 30 +- .../query-sync-storage-persister/src/utils.ts | 4 +- .../src/mockVisibilityState.ts | 1 + packages/query-test-utils/src/queryKey.ts | 4 +- packages/query-test-utils/src/sleep.ts | 4 +- .../src/ReactQueryDevtools.tsx | 44 +- .../src/ReactQueryDevtoolsPanel.tsx | 45 +- packages/react-query-devtools/src/index.ts | 3 +- .../src/HydrationStreamProvider.tsx | 76 +- .../src/ReactQueryStreamedHydration.tsx | 18 +- .../src/htmlescape.ts | 7 +- .../src/PersistQueryClientProvider.tsx | 21 +- .../react-query/src/HydrationBoundary.tsx | 85 +- .../react-query/src/IsRestoringProvider.ts | 15 +- .../react-query/src/QueryClientProvider.tsx | 53 +- .../src/QueryErrorResetBoundary.tsx | 157 +- .../react-query/src/errorBoundaryUtils.ts | 34 +- .../react-query/src/infiniteQueryOptions.ts | 257 +-- packages/react-query/src/mutationOptions.ts | 81 +- packages/react-query/src/queryOptions.ts | 228 ++- packages/react-query/src/suspense.ts | 26 +- packages/react-query/src/types.ts | 277 +-- packages/react-query/src/useBaseQuery.ts | 20 +- packages/react-query/src/useInfiniteQuery.ts | 440 ++--- packages/react-query/src/useIsFetching.ts | 48 +- packages/react-query/src/useMutation.ts | 249 +-- packages/react-query/src/useMutationState.ts | 127 +- .../src/usePrefetchInfiniteQuery.tsx | 77 +- packages/react-query/src/usePrefetchQuery.tsx | 58 +- packages/react-query/src/useQueries.ts | 273 +-- packages/react-query/src/useQuery.ts | 363 ++-- .../src/useSuspenseInfiniteQuery.ts | 143 +- .../react-query/src/useSuspenseQueries.ts | 502 +++--- packages/react-query/src/useSuspenseQuery.ts | 107 +- .../solid-query-devtools/src/clientOnly.tsx | 10 +- .../solid-query-devtools/src/devtools.tsx | 40 +- .../src/devtoolsPanel.tsx | 45 +- .../src/PersistQueryClientProvider.tsx | 21 +- packages/solid-query/src/QueryClient.ts | 57 +- .../solid-query/src/QueryClientProvider.tsx | 61 +- .../solid-query/src/infiniteQueryOptions.ts | 180 +- packages/solid-query/src/isRestoring.ts | 15 +- packages/solid-query/src/mutationOptions.ts | 81 +- packages/solid-query/src/queryOptions.ts | 136 +- packages/solid-query/src/types.ts | 171 +- packages/solid-query/src/useBaseQuery.ts | 61 +- packages/solid-query/src/useInfiniteQuery.ts | 249 +-- packages/solid-query/src/useIsFetching.ts | 34 +- packages/solid-query/src/useIsMutating.ts | 33 +- packages/solid-query/src/useMutation.ts | 230 +-- packages/solid-query/src/useMutationState.ts | 95 +- packages/solid-query/src/useQueries.ts | 150 +- packages/solid-query/src/useQuery.ts | 329 ++-- .../svelte-query-devtools/src/Devtools.svelte | 32 +- .../src/utils.svelte.ts | 4 +- .../svelte-query/src/containers.svelte.ts | 37 +- packages/svelte-query/src/context.ts | 41 +- .../src/createBaseQuery.svelte.ts | 6 +- .../svelte-query/src/createInfiniteQuery.ts | 169 +- .../svelte-query/src/createMutation.svelte.ts | 197 +- .../svelte-query/src/createQueries.svelte.ts | 108 +- packages/svelte-query/src/createQuery.ts | 277 +-- .../svelte-query/src/infiniteQueryOptions.ts | 124 +- packages/svelte-query/src/mutationOptions.ts | 59 +- packages/svelte-query/src/queryOptions.ts | 100 +- packages/svelte-query/src/types.ts | 44 +- packages/svelte-query/src/useHydrate.ts | 36 +- .../svelte-query/src/useIsFetching.svelte.ts | 45 +- .../svelte-query/src/useIsMutating.svelte.ts | 29 +- packages/svelte-query/src/useIsRestoring.ts | 25 +- .../src/useMutationState.svelte.ts | 88 +- packages/svelte-query/src/useQueryClient.ts | 22 +- packages/svelte-query/src/utils.svelte.ts | 18 +- packages/vue-query-devtools/src/types.ts | 79 +- packages/vue-query/src/devtools/devtools.ts | 5 +- packages/vue-query/src/devtools/utils.ts | 8 +- .../vue-query/src/infiniteQueryOptions.ts | 122 +- packages/vue-query/src/mutationCache.ts | 8 +- packages/vue-query/src/mutationOptions.ts | 174 +- packages/vue-query/src/queryCache.ts | 7 +- packages/vue-query/src/queryClient.ts | 127 +- packages/vue-query/src/queryOptions.ts | 299 ++-- packages/vue-query/src/types.ts | 77 +- packages/vue-query/src/useBaseQuery.ts | 30 +- packages/vue-query/src/useInfiniteQuery.ts | 317 ++-- packages/vue-query/src/useIsFetching.ts | 64 +- packages/vue-query/src/useMutation.ts | 213 +-- packages/vue-query/src/useMutationState.ts | 168 +- .../vue-query/src/usePrefetchInfiniteQuery.ts | 73 +- packages/vue-query/src/usePrefetchQuery.ts | 61 +- packages/vue-query/src/useQueries.ts | 183 +- packages/vue-query/src/useQuery.ts | 331 ++-- packages/vue-query/src/useQueryClient.ts | 33 +- packages/vue-query/src/utils.ts | 57 +- packages/vue-query/src/vueQueryPlugin.ts | 84 +- 257 files changed, 12562 insertions(+), 10556 deletions(-) diff --git a/docs/framework/react/plugins/broadcastQueryClient.md b/docs/framework/react/plugins/broadcastQueryClient.md index d67b3422a21..1deacb131ea 100644 --- a/docs/framework/react/plugins/broadcastQueryClient.md +++ b/docs/framework/react/plugins/broadcastQueryClient.md @@ -44,20 +44,22 @@ An object of options: interface BroadcastQueryClientOptions { /** The QueryClient to sync */ queryClient: QueryClient - /** This is the unique channel name that will be used - * to communicate between tabs and windows */ + /** + * This is the unique channel name that will be used to communicate between + * tabs and windows + */ broadcastChannel?: string /** Options for the BroadcastChannel API */ options?: BroadcastChannelOptions /** - * Called when a query event fails to broadcast to other tabs — most - * commonly because the query's data, error, or key contains a value the - * structured-clone algorithm cannot serialize (e.g. `ReadableStream`, - * `File`, functions, Vue `reactive` proxies). + * Called when a query event fails to broadcast to other tabs — most commonly + * because the query's data, error, or key contains a value the + * structured-clone algorithm cannot serialize (e.g. `ReadableStream`, `File`, + * functions, Vue `reactive` proxies). * - * If omitted, a `console.warn` is emitted in development so failures - * are never entirely silent. May return a `Promise`; any rejection is - * caught internally. + * If omitted, a `console.warn` is emitted in development so failures are + * never entirely silent. May return a `Promise`; any rejection is caught + * internally. */ onBroadcastError?: ( error: unknown, diff --git a/docs/framework/react/plugins/createAsyncStoragePersister.md b/docs/framework/react/plugins/createAsyncStoragePersister.md index 346de5fb237..3fa6df3540b 100644 --- a/docs/framework/react/plugins/createAsyncStoragePersister.md +++ b/docs/framework/react/plugins/createAsyncStoragePersister.md @@ -89,14 +89,16 @@ interface CreateAsyncStoragePersisterOptions { storage: AsyncStorage | undefined | null /** The key to use when storing the cache to localStorage */ key?: string - /** To avoid localStorage spamming, - * pass a time in ms to throttle saving the cache to disk */ + /** + * To avoid localStorage spamming, pass a time in ms to throttle saving the + * cache to disk + */ throttleTime?: number /** How to serialize the data to storage */ serialize?: (client: PersistedClient) => MaybePromise /** How to deserialize the data from storage */ deserialize?: (cachedString: string) => MaybePromise - /** How to retry persistence on error **/ + /** How to retry persistence on error * */ retry?: AsyncPersistRetryer } diff --git a/docs/framework/react/plugins/createPersister.md b/docs/framework/react/plugins/createPersister.md index fef03ed36b9..536371b0709 100644 --- a/docs/framework/react/plugins/createPersister.md +++ b/docs/framework/react/plugins/createPersister.md @@ -153,17 +153,20 @@ experimental_createQueryPersister(options: StoragePersisterOptions) ```tsx export interface StoragePersisterOptions { - /** The storage client used for setting and retrieving items from cache. - * For SSR pass in `undefined`. + /** + * The storage client used for setting and retrieving items from cache. For + * SSR pass in `undefined`. */ storage: AsyncStorage | Storage | undefined | null /** * How to serialize the data to storage. + * * @default `JSON.stringify` */ serialize?: (persistedQuery: PersistedQuery) => string /** * How to deserialize the data from storage. + * * @default `JSON.parse` */ deserialize?: (cachedString: string) => PersistedQuery @@ -173,27 +176,25 @@ export interface StoragePersisterOptions { */ buster?: string /** - * The max-allowed age of the cache in milliseconds. - * If a persisted cache is found that is older than this - * time, it will be discarded + * The max-allowed age of the cache in milliseconds. If a persisted cache is + * found that is older than this time, it will be discarded + * * @default 24 hours */ maxAge?: number /** - * Prefix to be used for storage key. - * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`. + * Prefix to be used for storage key. Storage key is a combination of prefix + * and query hash in a form of `prefix-queryHash`. */ prefix?: string /** - * If set to `true`, the query will refetch on successful query restoration if the data is stale. - * If set to `false`, the query will not refetch on successful query restoration. - * If set to `'always'`, the query will always refetch on successful query restoration. - * Defaults to `true`. + * If set to `true`, the query will refetch on successful query restoration if + * the data is stale. If set to `false`, the query will not refetch on + * successful query restoration. If set to `'always'`, the query will always + * refetch on successful query restoration. Defaults to `true`. */ refetchOnRestore?: boolean | 'always' - /** - * Filters to narrow down which Queries should be persisted. - */ + /** Filters to narrow down which Queries should be persisted. */ filters?: QueryFilters } diff --git a/docs/framework/react/plugins/createSyncStoragePersister.md b/docs/framework/react/plugins/createSyncStoragePersister.md index 912b48f446b..7ffddc6d96a 100644 --- a/docs/framework/react/plugins/createSyncStoragePersister.md +++ b/docs/framework/react/plugins/createSyncStoragePersister.md @@ -105,18 +105,20 @@ createSyncStoragePersister(options: CreateSyncStoragePersisterOptions) ```tsx interface CreateSyncStoragePersisterOptions { - /** The storage client used for setting an retrieving items from cache (window.localStorage or window.sessionStorage) */ + /** + * The storage client used for setting an retrieving items from cache + * (window.localStorage or window.sessionStorage) + */ storage: Storage | undefined | null /** The key to use when storing the cache */ key?: string - /** To avoid spamming, - * pass a time in ms to throttle saving the cache to disk */ + /** To avoid spamming, pass a time in ms to throttle saving the cache to disk */ throttleTime?: number /** How to serialize the data to storage */ serialize?: (client: PersistedClient) => string /** How to deserialize the data from storage */ deserialize?: (cachedString: string) => PersistedClient - /** How to retry persistence on error **/ + /** How to retry persistence on error * */ retry?: PersistRetryer } ``` diff --git a/docs/framework/react/plugins/persistQueryClient.md b/docs/framework/react/plugins/persistQueryClient.md index 2597610f356..6eb336357fe 100644 --- a/docs/framework/react/plugins/persistQueryClient.md +++ b/docs/framework/react/plugins/persistQueryClient.md @@ -133,22 +133,31 @@ All options available are as follows: interface PersistQueryClientOptions { /** The QueryClient to persist */ queryClient: QueryClient - /** The Persister interface for storing and restoring the cache - * to/from a persisted location */ + /** + * The Persister interface for storing and restoring the cache to/from a + * persisted location + */ persister: Persister - /** The max-allowed age of the cache in milliseconds. - * If a persisted cache is found that is older than this - * time, it will be **silently** discarded - * (defaults to 24 hours) */ + /** + * The max-allowed age of the cache in milliseconds. If a persisted cache is + * found that is older than this time, it will be **silently** discarded + * (defaults to 24 hours) + */ maxAge?: number - /** A unique string that can be used to forcefully - * invalidate existing caches if they do not share the same buster string */ + /** + * A unique string that can be used to forcefully invalidate existing caches + * if they do not share the same buster string + */ buster?: string - /** The options passed to the hydrate function - * Not used on `persistQueryClientSave` or `persistQueryClientSubscribe` */ + /** + * The options passed to the hydrate function Not used on + * `persistQueryClientSave` or `persistQueryClientSubscribe` + */ hydrateOptions?: HydrateOptions - /** The options passed to the dehydrate function - * Not used on `persistQueryClientRestore` */ + /** + * The options passed to the dehydrate function Not used on + * `persistQueryClientRestore` + */ dehydrateOptions?: DehydrateOptions } ``` @@ -274,6 +283,7 @@ import { /** * Creates an Indexed DB persister + * * @see https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API */ export function createIDBPersister(idbValidKey: IDBValidKey = 'reactQuery') { diff --git a/docs/framework/vue/plugins/createPersister.md b/docs/framework/vue/plugins/createPersister.md index fd3eec58d9e..a7c8fc27e77 100644 --- a/docs/framework/vue/plugins/createPersister.md +++ b/docs/framework/vue/plugins/createPersister.md @@ -150,17 +150,20 @@ experimental_createQueryPersister(options: StoragePersisterOptions) ```tsx export interface StoragePersisterOptions { - /** The storage client used for setting and retrieving items from cache. - * For SSR pass in `undefined`. + /** + * The storage client used for setting and retrieving items from cache. For + * SSR pass in `undefined`. */ storage: AsyncStorage | Storage | undefined | null /** * How to serialize the data to storage. + * * @default `JSON.stringify` */ serialize?: (persistedQuery: PersistedQuery) => string /** * How to deserialize the data from storage. + * * @default `JSON.parse` */ deserialize?: (cachedString: string) => PersistedQuery @@ -170,27 +173,25 @@ export interface StoragePersisterOptions { */ buster?: string /** - * The max-allowed age of the cache in milliseconds. - * If a persisted cache is found that is older than this - * time, it will be discarded + * The max-allowed age of the cache in milliseconds. If a persisted cache is + * found that is older than this time, it will be discarded + * * @default 24 hours */ maxAge?: number /** - * Prefix to be used for storage key. - * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`. + * Prefix to be used for storage key. Storage key is a combination of prefix + * and query hash in a form of `prefix-queryHash`. */ prefix?: string /** - * If set to `true`, the query will refetch on successful query restoration if the data is stale. - * If set to `false`, the query will not refetch on successful query restoration. - * If set to `'always'`, the query will always refetch on successful query restoration. - * Defaults to `true`. + * If set to `true`, the query will refetch on successful query restoration if + * the data is stale. If set to `false`, the query will not refetch on + * successful query restoration. If set to `'always'`, the query will always + * refetch on successful query restoration. Defaults to `true`. */ refetchOnRestore?: boolean | 'always' - /** - * Filters to narrow down which Queries should be persisted. - */ + /** Filters to narrow down which Queries should be persisted. */ filters?: QueryFilters } diff --git a/examples/angular/auto-refetching/src/app/interceptor/mock-api.interceptor.ts b/examples/angular/auto-refetching/src/app/interceptor/mock-api.interceptor.ts index be66dada97b..d0ad6d0bd79 100644 --- a/examples/angular/auto-refetching/src/app/interceptor/mock-api.interceptor.ts +++ b/examples/angular/auto-refetching/src/app/interceptor/mock-api.interceptor.ts @@ -1,10 +1,11 @@ /** - * MockApiInterceptor is used to simulate API responses for `/api/tasks` endpoints. - * It handles the following operations: + * MockApiInterceptor is used to simulate API responses for `/api/tasks` + * endpoints. It handles the following operations: + * * - GET: Fetches all tasks from localStorage. * - POST: Adds a new task to localStorage. - * - DELETE: Clears all tasks from localStorage. - * Simulated responses include a delay to mimic network latency. + * - DELETE: Clears all tasks from localStorage. Simulated responses include a + * delay to mimic network latency. */ import { HttpResponse } from '@angular/common/http' import { delay, of } from 'rxjs' diff --git a/examples/angular/auto-refetching/src/app/services/tasks.service.ts b/examples/angular/auto-refetching/src/app/services/tasks.service.ts index 41d3dacb27d..cf90f2793c4 100644 --- a/examples/angular/auto-refetching/src/app/services/tasks.service.ts +++ b/examples/angular/auto-refetching/src/app/services/tasks.service.ts @@ -16,8 +16,8 @@ export class TasksService { readonly #http = inject(HttpClient) // Handles HTTP requests /** - * Fetches all tasks from the API. - * Returns an observable containing an array of task strings. + * Fetches all tasks from the API. Returns an observable containing an array + * of task strings. */ allTasks = (intervalMs: number) => queryOptions({ @@ -29,8 +29,8 @@ export class TasksService { }) /** - * Creates a mutation for adding a task. - * On success, invalidates and refetches the "tasks" query cache to update the task list. + * Creates a mutation for adding a task. On success, invalidates and refetches + * the "tasks" query cache to update the task list. */ addTask() { return mutationOptions({ @@ -44,8 +44,8 @@ export class TasksService { } /** - * Creates a mutation for clearing all tasks. - * On success, invalidates and refetches the "tasks" query cache to ensure consistency. + * Creates a mutation for clearing all tasks. On success, invalidates and + * refetches the "tasks" query cache to ensure consistency. */ clearAllTasks() { return mutationOptions({ diff --git a/examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts b/examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts index 9617b80f923..9ad5cab99d3 100644 --- a/examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts +++ b/examples/angular/optimistic-updates/src/app/interceptor/mock-api.interceptor.ts @@ -1,9 +1,10 @@ /** - * MockApiInterceptor is used to simulate API responses for `/api/tasks` endpoints. - * It handles the following operations: + * MockApiInterceptor is used to simulate API responses for `/api/tasks` + * endpoints. It handles the following operations: + * * - GET: Fetches all tasks from sessionStorage. - * - POST: Adds a new task to sessionStorage. - * Simulated responses include a delay to mimic network latency. + * - POST: Adds a new task to sessionStorage. Simulated responses include a delay + * to mimic network latency. */ import { HttpErrorResponse, HttpResponse } from '@angular/common/http' import { delay, of, switchMap, throwError, timer } from 'rxjs' diff --git a/examples/angular/optimistic-updates/src/app/services/tasks.service.ts b/examples/angular/optimistic-updates/src/app/services/tasks.service.ts index ae3305ad1f6..e475a51e47d 100644 --- a/examples/angular/optimistic-updates/src/app/services/tasks.service.ts +++ b/examples/angular/optimistic-updates/src/app/services/tasks.service.ts @@ -16,8 +16,8 @@ export class TasksService { #http = inject(HttpClient) // Handles HTTP requests /** - * Fetches all tasks from the API. - * Returns an observable containing an array of task strings. + * Fetches all tasks from the API. Returns an observable containing an array + * of task strings. */ allTasks = () => queryOptions({ @@ -28,8 +28,8 @@ export class TasksService { }) /** - * Creates a mutation for adding a task. - * On success, invalidates and refetches the "tasks" query cache to update the task list. + * Creates a mutation for adding a task. On success, invalidates and refetches + * the "tasks" query cache to update the task list. */ addTask() { return mutationOptions({ diff --git a/examples/react/offline/public/mockServiceWorker.js b/examples/react/offline/public/mockServiceWorker.js index 0c970efc963..f27de5e6368 100644 --- a/examples/react/offline/public/mockServiceWorker.js +++ b/examples/react/offline/public/mockServiceWorker.js @@ -3,6 +3,7 @@ /** * Mock Service Worker. + * * @see https://github.com/mswjs/msw * - Please do NOT modify this file. */ @@ -179,10 +180,11 @@ async function handleRequest(event, requestId, requestInterceptedAt) { } /** - * Resolve the main client for the given event. - * Client that issues a request doesn't necessarily equal the client - * that registered the worker. It's with the latter the worker should - * communicate with during the response resolving phase. + * Resolve the main client for the given event. Client that issues a request + * doesn't necessarily equal the client that registered the worker. It's with + * the latter the worker should communicate with during the response resolving + * phase. + * * @param {FetchEvent} event * @returns {Promise} */ @@ -294,7 +296,7 @@ async function getResponse(event, client, requestId, requestInterceptedAt) { /** * @param {Client} client * @param {any} message - * @param {Array} transferrables + * @param {Transferable[]} transferrables * @returns {Promise} */ function sendToClient(client, message, transferrables = []) { @@ -339,9 +341,7 @@ function respondWithMock(response) { return mockedResponse } -/** - * @param {Request} request - */ +/** @param {Request} request */ async function serializeRequest(request) { return { url: request.url, diff --git a/examples/solid/offline/public/mockServiceWorker.js b/examples/solid/offline/public/mockServiceWorker.js index 0c970efc963..f27de5e6368 100644 --- a/examples/solid/offline/public/mockServiceWorker.js +++ b/examples/solid/offline/public/mockServiceWorker.js @@ -3,6 +3,7 @@ /** * Mock Service Worker. + * * @see https://github.com/mswjs/msw * - Please do NOT modify this file. */ @@ -179,10 +180,11 @@ async function handleRequest(event, requestId, requestInterceptedAt) { } /** - * Resolve the main client for the given event. - * Client that issues a request doesn't necessarily equal the client - * that registered the worker. It's with the latter the worker should - * communicate with during the response resolving phase. + * Resolve the main client for the given event. Client that issues a request + * doesn't necessarily equal the client that registered the worker. It's with + * the latter the worker should communicate with during the response resolving + * phase. + * * @param {FetchEvent} event * @returns {Promise} */ @@ -294,7 +296,7 @@ async function getResponse(event, client, requestId, requestInterceptedAt) { /** * @param {Client} client * @param {any} message - * @param {Array} transferrables + * @param {Transferable[]} transferrables * @returns {Promise} */ function sendToClient(client, message, transferrables = []) { @@ -339,9 +341,7 @@ function respondWithMock(response) { return mockedResponse } -/** - * @param {Request} request - */ +/** @param {Request} request */ async function serializeRequest(request) { return { url: request.url, diff --git a/examples/solid/solid-start-streaming/src/components/query-boundary.tsx b/examples/solid/solid-start-streaming/src/components/query-boundary.tsx index 01d5381fcd6..c4669d40c33 100644 --- a/examples/solid/solid-start-streaming/src/components/query-boundary.tsx +++ b/examples/solid/solid-start-streaming/src/components/query-boundary.tsx @@ -12,30 +12,23 @@ import type { JSX } from 'solid-js' export interface QueryBoundaryProps { query: UseQueryResult - /** - * Triggered when the data is initially loading. - */ + /** Triggered when the data is initially loading. */ loadingFallback?: JSX.Element - /** - * Triggered when fetching is complete, but the returned data was falsey. - */ + /** Triggered when fetching is complete, but the returned data was falsey. */ notFoundFallback?: JSX.Element - /** - * Triggered when the query results in an error. - */ + /** Triggered when the query results in an error. */ errorFallback?: (err: Error, retry: () => void) => JSX.Element - /** - * Triggered when fetching is complete, and the returned data is not falsey. - */ + /** Triggered when fetching is complete, and the returned data is not falsey. */ children: (data: Exclude) => JSX.Element } /** - * Convenience wrapper that handles suspense and errors for queries. Makes the results of query.data available to - * children (as a render prop) in a type-safe way. + * Convenience wrapper that handles suspense and errors for queries. Makes the + * results of query.data available to children (as a render prop) in a type-safe + * way. */ export function QueryBoundary(props: QueryBoundaryProps) { const retry = async (reset: () => void) => { diff --git a/integrations/react-next-15/app/make-query-client.ts b/integrations/react-next-15/app/make-query-client.ts index a71affe77fa..4d140603df4 100644 --- a/integrations/react-next-15/app/make-query-client.ts +++ b/integrations/react-next-15/app/make-query-client.ts @@ -23,8 +23,8 @@ export function makeQueryClient() { defaultOptions: { hydrate: { /** - * Called when the query is rebuilt from a prefetched - * promise, before the query data is put into the cache. + * Called when the query is rebuilt from a prefetched promise, before + * the query data is put into the cache. */ deserializeData: (data) => { return tson.deserialize(data) diff --git a/integrations/react-next-16/app/make-query-client.ts b/integrations/react-next-16/app/make-query-client.ts index a71affe77fa..4d140603df4 100644 --- a/integrations/react-next-16/app/make-query-client.ts +++ b/integrations/react-next-16/app/make-query-client.ts @@ -23,8 +23,8 @@ export function makeQueryClient() { defaultOptions: { hydrate: { /** - * Called when the query is rebuilt from a prefetched - * promise, before the query data is put into the cache. + * Called when the query is rebuilt from a prefetched promise, before + * the query data is put into the cache. */ deserializeData: (data) => { return tson.deserialize(data) diff --git a/oxfmt.config.ts b/oxfmt.config.ts index c49a240de7a..059e37d68fd 100644 --- a/oxfmt.config.ts +++ b/oxfmt.config.ts @@ -6,6 +6,7 @@ export default defineConfig({ trailingComma: 'all', printWidth: 80, sortPackageJson: false, + jsdoc: true, svelte: {}, ignorePatterns: [ '**/.next', diff --git a/oxlint.config.ts b/oxlint.config.ts index 940ca0b2366..beb0ea26908 100644 --- a/oxlint.config.ts +++ b/oxlint.config.ts @@ -5,8 +5,8 @@ import { defineConfig } from 'oxlint' /** * Oxlint ships a native `jsdoc` plugin that only covers part of - * 'eslint-plugin-jsdoc', so the original plugin is loaded as a JS plugin - * under the `jsdoc-js` alias and its recommended rules are renamed to match. + * 'eslint-plugin-jsdoc', so the original plugin is loaded as a JS plugin under + * the `jsdoc-js` alias and its recommended rules are renamed to match. */ const jsdocRecommendedRules = Object.fromEntries( Object.entries( @@ -179,12 +179,13 @@ export default defineConfig({ ], /** - * Disallows direct calls to deprecated imperative query methods of `QueryClient` - * for new tests and code + * Disallows direct calls to deprecated imperative query methods of + * `QueryClient` for new tests and code * * Existing tests that directly test the methods from before the refactoring - * will be grandfathered in and allowed to continue using the deprecated methods. - * They should not be removed, but new tests should use the new methods instead. + * will be grandfathered in and allowed to continue using the deprecated + * methods. They should not be removed, but new tests should use the new + * methods instead. */ 'tanstack-query/no-restricted-syntax': [ 'error', @@ -300,12 +301,13 @@ export default defineConfig({ }) /** - * Native Oxlint equivalent of 'eslint-config-preact', applied on top of the root config. + * Native Oxlint equivalent of 'eslint-config-preact', applied on top of the + * root config. * - * Not ported because Oxlint does not implement them: `no-dupe-args`, `no-undef`, - * `no-undef-init`, `strict`, `react/jsx-no-bind`, `react/jsx-uses-react`, - * `react/jsx-uses-vars`, `react/no-deprecated`, `react/prefer-stateless-function` - * and `react/require-render-return`. + * Not ported because Oxlint does not implement them: `no-dupe-args`, + * `no-undef`, `no-undef-init`, `strict`, `react/jsx-no-bind`, + * `react/jsx-uses-react`, `react/jsx-uses-vars`, `react/no-deprecated`, + * `react/prefer-stateless-function` and `react/require-render-return`. */ export const preactConfig = defineConfig({ plugins: ['import', 'typescript', 'unicorn', 'vitest', 'react'], diff --git a/packages/angular-query-experimental/scripts/prepack.js b/packages/angular-query-experimental/scripts/prepack.js index bf4bef0cc75..22669d8f9ed 100644 --- a/packages/angular-query-experimental/scripts/prepack.js +++ b/packages/angular-query-experimental/scripts/prepack.js @@ -3,25 +3,31 @@ import path from 'node:path' /** * Prepack script that prepares the package for publishing by: - * 1. Creating a modified package.json without dev dependencies, publishConfig and build scripts - * 2. Updating file paths to remove 'dist/' prefixes (since files will be at root in published package) + * + * 1. Creating a modified package.json without dev dependencies, publishConfig and + * build scripts + * 2. Updating file paths to remove 'dist/' prefixes (since files will be at root + * in published package) * 3. Writing this modified package.json to the `dist` directory * 4. Copying additional files like README.md to the dist directory * - * Type declarations need to be in the package root or corresponding sub-path to support - * sub-path exports in applications still using `moduleResolution: node`. + * Type declarations need to be in the package root or corresponding sub-path to + * support sub-path exports in applications still using `moduleResolution: + * node`. */ console.log('Running prepack script') /** * Files to copy to the dist directory + * * @type {string[]} */ const FILES_TO_COPY = ['README.md'] /** * Fields to remove from the package.json copy + * * @type {string[]} */ const FIELDS_TO_REMOVE = [ @@ -32,8 +38,9 @@ const FIELDS_TO_REMOVE = [ ] /** - * Replaces 'dist/' or './dist/' prefix from a file path with './' - * Only matches at the start of the path to avoid false matches + * Replaces 'dist/' or './dist/' prefix from a file path with './' Only matches + * at the start of the path to avoid false matches + * * @param {string} filePath - The file path to process * @returns {string} The path without dist prefix */ @@ -45,6 +52,7 @@ function replaceDist(filePath) { /** * Recursively processes package.json `exports` to remove dist prefixes + * * @param {Record} exports - The exports object to process * @returns {Record} The processed exports object */ diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts index 9627483e18c..d763fc8f92c 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts @@ -64,9 +64,6 @@ describe('injectQuery', () => { injectQuery(() => ({ queryKey: key, queryFn: () => 'test' })) // it should infer the result type from a generic query function - /** - * - */ function queryFn(): Promise { return Promise.resolve({} as T) } diff --git a/packages/angular-query-experimental/src/__tests__/test-utils.ts b/packages/angular-query-experimental/src/__tests__/test-utils.ts index 33ded6b2eea..15e7f6aca0a 100644 --- a/packages/angular-query-experimental/src/__tests__/test-utils.ts +++ b/packages/angular-query-experimental/src/__tests__/test-utils.ts @@ -52,6 +52,7 @@ function componentHasSignalInputProperty( /** * Set required signal input value to component fixture + * * @see https://github.com/angular/angular/issues/54013 */ export function setSignalInputs>( diff --git a/packages/angular-query-experimental/src/create-base-query.ts b/packages/angular-query-experimental/src/create-base-query.ts index 89bb6b692b2..53272b641a7 100644 --- a/packages/angular-query-experimental/src/create-base-query.ts +++ b/packages/angular-query-experimental/src/create-base-query.ts @@ -25,11 +25,13 @@ import type { CreateBaseQueryOptions } from './types' /** * Base implementation for `injectQuery` and `injectInfiniteQuery`. - * @param optionsFn - A function that returns the query options. It is re-run when the signals it - * reads change. - * @param Observer - The observer class from query-core (`QueryObserver` or `InfiniteQueryObserver`). - * @returns The query result, with each value field exposed as a computed signal. Functions such as - * `refetch` stay callable functions. + * + * @param optionsFn - A function that returns the query options. It is re-run + * when the signals it reads change. + * @param Observer - The observer class from query-core (`QueryObserver` or + * `InfiniteQueryObserver`). + * @returns The query result, with each value field exposed as a computed + * signal. Functions such as `refetch` stay callable functions. */ export function createBaseQuery< TQueryFnData, @@ -53,10 +55,10 @@ export function createBaseQuery< const isRestoring = injectIsRestoring() /** - * Signal that has the default options from query client applied - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes + * Signal that has the default options from query client applied computed() is + * used so signals can be inserted into the options making it reactive. + * Wrapping options in a function ensures embedded expressions are preserved + * and can keep being applied after signal changes */ const defaultedOptionsSignal = computed(() => { const defaultedOptions = queryClient.defaultQueryOptions(optionsFn()) diff --git a/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts b/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts index 94aaa185ca7..fd3012a5605 100644 --- a/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts +++ b/packages/angular-query-experimental/src/devtools-panel/inject-devtools-panel.ts @@ -21,11 +21,13 @@ import type { /** * Inject a TanStack Query devtools panel and render it in the DOM. * - * Devtools panel allows programmatic control over the devtools, for example if you want to render - * the devtools as part of your own devtools. + * Devtools panel allows programmatic control over the devtools, for example if + * you want to render the devtools as part of your own devtools. * * Consider `withDevtools` instead if you don't need this. - * @param injectDevtoolsPanelFn - A function that returns devtools panel options. + * + * @param injectDevtoolsPanelFn - A function that returns devtools panel + * options. * @param options - Additional configuration * @returns DevtoolsPanelRef * @see https://tanstack.com/query/v5/docs/framework/angular/devtools diff --git a/packages/angular-query-experimental/src/devtools-panel/stub.ts b/packages/angular-query-experimental/src/devtools-panel/stub.ts index ab52842f48a..33f8f712ab5 100644 --- a/packages/angular-query-experimental/src/devtools-panel/stub.ts +++ b/packages/angular-query-experimental/src/devtools-panel/stub.ts @@ -2,7 +2,9 @@ import { noop } from '@tanstack/query-core' import type { InjectDevtoolsPanel } from './types' /** - * Replaces `injectDevtoolsPanel` in production builds: returns a panel whose `destroy` does nothing. + * Replaces `injectDevtoolsPanel` in production builds: returns a panel whose + * `destroy` does nothing. + * * @returns A devtools panel that does nothing. */ export const injectDevtoolsPanel: InjectDevtoolsPanel = () => ({ diff --git a/packages/angular-query-experimental/src/devtools-panel/types.ts b/packages/angular-query-experimental/src/devtools-panel/types.ts index 840dd7b1e25..0a13cbdcf60 100644 --- a/packages/angular-query-experimental/src/devtools-panel/types.ts +++ b/packages/angular-query-experimental/src/devtools-panel/types.ts @@ -2,64 +2,63 @@ import type { DevtoolsErrorType } from '@tanstack/query-devtools' import type { ElementRef, Injector } from '@angular/core' import type { QueryClient } from '@tanstack/query-core' -/** - * Options for `injectDevtoolsPanel`. - */ +/** Options for `injectDevtoolsPanel`. */ export interface InjectDevtoolsPanelOptions { /** * The `Injector` in which to create the devtools panel. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } -/** - * A devtools panel, which can be manually destroyed. - */ +/** A devtools panel, which can be manually destroyed. */ export interface DevtoolsPanelRef { /** - * Destroy the panel, removing it from the DOM and stops listening to signal changes. + * Destroy the panel, removing it from the DOM and stops listening to signal + * changes. */ destroy: () => void } /** - * Options for the devtools panel, returned by the function passed to `injectDevtoolsPanel`. + * Options for the devtools panel, returned by the function passed to + * `injectDevtoolsPanel`. */ export interface DevtoolsPanelOptions { - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Callback function that is called when the devtools panel is closed - */ + /** Callback function that is called when the devtools panel is closed */ onClose?: () => void /** - * Element where to render the devtools panel. When set to undefined or null, the devtools panel will not be created, or destroyed if existing. - * If changed from undefined to an ElementRef, the devtools panel will be created. + * Element where to render the devtools panel. When set to undefined or null, + * the devtools panel will not be created, or destroyed if existing. If + * changed from undefined to an ElementRef, the devtools panel will be + * created. */ hostElement?: ElementRef } /** - * The signature of `injectDevtoolsPanel`, which creates a devtools panel from reactive options. + * The signature of `injectDevtoolsPanel`, which creates a devtools panel from + * reactive options. */ export type InjectDevtoolsPanel = ( injectDevtoolsPanelFn: () => DevtoolsPanelOptions, diff --git a/packages/angular-query-experimental/src/devtools/stub.ts b/packages/angular-query-experimental/src/devtools/stub.ts index 5b14ce44775..44cd7b465fd 100644 --- a/packages/angular-query-experimental/src/devtools/stub.ts +++ b/packages/angular-query-experimental/src/devtools/stub.ts @@ -1,7 +1,9 @@ import type { WithDevtools } from './types' /** - * Replaces `withDevtools` in production builds: returns the devtools feature with no providers. + * Replaces `withDevtools` in production builds: returns the devtools feature + * with no providers. + * * @returns A devtools feature that does nothing. */ export const withDevtools: WithDevtools = () => ({ diff --git a/packages/angular-query-experimental/src/devtools/types.ts b/packages/angular-query-experimental/src/devtools/types.ts index 1c65637bf24..247f2707bba 100644 --- a/packages/angular-query-experimental/src/devtools/types.ts +++ b/packages/angular-query-experimental/src/devtools/types.ts @@ -7,14 +7,14 @@ import type { } from '@tanstack/query-devtools' import type { DevtoolsFeature } from '../providers' -/** - * Options for configuring withDevtools. - */ +/** Options for configuring withDevtools. */ export interface WithDevtoolsOptions { /** - * An array of dependencies to be injected and passed to the `withDevtoolsFn` function. + * An array of dependencies to be injected and passed to the `withDevtoolsFn` + * function. * * **Example** + * * ```ts * export const appConfig: ApplicationConfig = { * providers: [ @@ -36,85 +36,88 @@ export interface WithDevtoolsOptions { deps?: Array } -/** - * Options for configuring the TanStack Query devtools. - */ +/** Options for configuring the TanStack Query devtools. */ export interface DevtoolsOptions { - /** - * Set this true if you want the devtools to default to being open - */ + /** Set this true if you want the devtools to default to being open */ initialIsOpen?: boolean /** * The position of the TanStack logo to open and close the devtools panel. * `top-left` | `top-right` | `bottom-left` | `bottom-right` | `relative` + * * @defaultValue bottom-right */ buttonPosition?: DevtoolsButtonPosition /** - * The position of the Angular Query devtools panel. - * `top` | `bottom` | `left` | `right` + * The position of the Angular Query devtools panel. `top` | `bottom` | `left` + * | `right` + * * @defaultValue bottom */ position?: DevtoolsPosition - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Set this to true to hide disabled queries from the devtools panel. - */ + /** Set this to true to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Set this to 'light', 'dark', or 'system' to change the theme of the + * devtools panel. + * * @defaultValue system */ theme?: Theme /** * Whether the developer tools should load. - * - `auto`- (Default) Lazily loads devtools when in development mode. Skips loading in production mode. + * + * - `auto`- (Default) Lazily loads devtools when in development mode. Skips + * loading in production mode. * - `true`- Always load the devtools, regardless of the environment. * - `false`- Never load the devtools, regardless of the environment. * - * You can use `true` and `false` to override loading developer tools from an environment file. - * For example, a test environment might run in production mode but you may want to load developer tools. + * You can use `true` and `false` to override loading developer tools from an + * environment file. For example, a test environment might run in production + * mode but you may want to load developer tools. * - * Additionally, you can use a signal in the callback to dynamically load the devtools based on a condition. For example, - * a signal created from a RxJS observable that listens for a keyboard shortcut. + * Additionally, you can use a signal in the callback to dynamically load the + * devtools based on a condition. For example, a signal created from a RxJS + * observable that listens for a keyboard shortcut. * * **Example** + * * ```ts - * withDevtools(() => ({ - * initialIsOpen: true, - * loadDevtools: inject(ExampleService).loadDevtools() - * })) - * ``` + * withDevtools(() => ({ + * initialIsOpen: true, + * loadDevtools: inject(ExampleService).loadDevtools(), + * })) + * ``` */ loadDevtools?: 'auto' | boolean } /** * A function that returns the devtools options. It receives the `deps` of - * {@link WithDevtoolsOptions} and runs inside a `computed`, so the devtools update when the signals - * it reads change. + * {@link WithDevtoolsOptions} and runs inside a `computed`, so the devtools + * update when the signals it reads change. */ export type WithDevtoolsFn = (...deps: Array) => DevtoolsOptions /** - * The signature of `withDevtools`, which creates the devtools feature for `provideTanStackQuery`. + * The signature of `withDevtools`, which creates the devtools feature for + * `provideTanStackQuery`. */ export type WithDevtools = ( withDevtoolsFn?: WithDevtoolsFn, diff --git a/packages/angular-query-experimental/src/devtools/with-devtools.ts b/packages/angular-query-experimental/src/devtools/with-devtools.ts index 4d4b861c7f2..7166636ea89 100644 --- a/packages/angular-query-experimental/src/devtools/with-devtools.ts +++ b/packages/angular-query-experimental/src/devtools/with-devtools.ts @@ -22,7 +22,8 @@ import type { import type { TanstackQueryDevtools } from '@tanstack/query-devtools' /** - * Internal token used to prevent double providing of devtools in child injectors + * Internal token used to prevent double providing of devtools in child + * injectors */ const DEVTOOLS_PROVIDED = new InjectionToken('', { factory: () => ({ @@ -30,9 +31,7 @@ const DEVTOOLS_PROVIDED = new InjectionToken('', { }), }) -/** - * Internal token for providing devtools options - */ +/** Internal token for providing devtools options */ const DEVTOOLS_OPTIONS_SIGNAL = new InjectionToken>('') /** @@ -42,16 +41,19 @@ const DEVTOOLS_OPTIONS_SIGNAL = new InjectionToken>('') * * ```ts * export const appConfig: ApplicationConfig = { - * providers: [ - * provideTanStackQuery(new QueryClient(), withDevtools()) - * ] + * providers: [provideTanStackQuery(new QueryClient(), withDevtools())], * } * ``` + * * The devtools will be rendered in ``. * - * If you need more control over when devtools are loaded, you can use the `loadDevtools` option. + * If you need more control over when devtools are loaded, you can use the + * `loadDevtools` option. + * + * If you need more control over where devtools are rendered, consider + * `injectDevtoolsPanel`. This allows rendering devtools inside your own + * devtools for example. * - * If you need more control over where devtools are rendered, consider `injectDevtoolsPanel`. This allows rendering devtools inside your own devtools for example. * @param withDevtoolsFn - A function that returns `DevtoolsOptions`. * @param options - Additional options for configuring `withDevtools`. * @returns A set of providers for use with `provideTanStackQuery`. diff --git a/packages/angular-query-experimental/src/infinite-query-options.ts b/packages/angular-query-experimental/src/infinite-query-options.ts index d0c59383a1b..f2376045ad3 100644 --- a/packages/angular-query-experimental/src/infinite-query-options.ts +++ b/packages/angular-query-experimental/src/infinite-query-options.ts @@ -11,14 +11,19 @@ import type { import type { CreateInfiniteQueryOptions } from './types' /** - * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data` - * may be `undefined` while the query is `pending`. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UndefinedInitialDataInfiniteOptions< TQueryFnData, @@ -34,11 +39,12 @@ export type UndefinedInitialDataInfiniteOptions< TPageParam > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData?: | undefined @@ -49,15 +55,20 @@ export type UndefinedInitialDataInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set and - * `queryFn` is not `skipToken` — same as {@link UndefinedInitialDataInfiniteOptions}, but `queryFn` may not be + * The options accepted by the `infiniteQueryOptions` overload selected when no + * `initialData` is set and `queryFn` is not `skipToken` — same as + * {@link UndefinedInitialDataInfiniteOptions}, but `queryFn` may not be * `skipToken`. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UnusedSkipTokenInfiniteOptions< TQueryFnData, @@ -76,10 +87,12 @@ export type UnusedSkipTokenInfiniteOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If - * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a - * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been - * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own. + * `skipToken` is not allowed as a value here — this overload is selected when + * no `initialData` is set. If you don't intend to run the query yet, set + * `enabled: false` — omitting `queryFn` alone still triggers a fetch that + * fails with "Missing queryFn" unless `enabled` is `false` or a default query + * function has been defined. A default query function only supplies + * `queryFn`; it doesn't defer the fetch on its own. */ queryFn?: Exclude< CreateInfiniteQueryOptions< @@ -94,14 +107,19 @@ export type UnusedSkipTokenInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is - * never `undefined` (unless a `select` changes `TData` to include `undefined`). - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type DefinedInitialDataInfiniteOptions< TQueryFnData, @@ -117,11 +135,12 @@ export type DefinedInitialDataInfiniteOptions< TPageParam > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData: | NonUndefinedGuard> @@ -130,48 +149,52 @@ export type DefinedInitialDataInfiniteOptions< } /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to - * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as - * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options - * for. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `injectInfiniteQuery`. These options can be shared across functions + * and imperative APIs such as `queryClient.fetchInfiniteQuery`. + * `options.queryKey` is required and is the query key to generate options for. * * This overload is selected when `initialData` is set. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `injectInfiniteQuery`, with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages, from a button click or - * automatically as the user scrolls. - * @see {@link injectInfiniteQuery} to run an infinite query with these options. + * + * @remarks + * See {@link injectInfiniteQuery} for examples that fetch further pages, from + * a button click or automatically as the user scrolls. * @example - * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * ```angular-ts + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' * - * export const projectsOptions = infiniteQueryOptions({ + * export const projectsOptions = infiniteQueryOptions({ * queryKey: ['projects'], * queryFn: ({ pageParam }) => fetchProjects(pageParam), * initialPageParam: 0, * getNextPageParam: (lastPage) => lastPage.nextId, * initialData: { pages: [], pageParams: [] }, - * }) + * }) * - * @Component({ + * @Component({ * selector: 'projects', * template: ` - * - *
    - * @for (page of projectsQuery.data().pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
+ * + *
    + * @for (page of projectsQuery.data().pages; track $index) { + * @for (project of page.projects; track project.id) { + *
  • {{ project.name }}
  • + * } + * } + *
* `, - * }) - * export class Projects { + * }) + * export class Projects { * readonly projectsQuery = injectInfiniteQuery(() => projectsOptions) - * } - * ``` + * } + * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `injectInfiniteQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -197,52 +220,56 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to - * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as - * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options - * for. - * @param options - The {@link UnusedSkipTokenInfiniteOptions} to use — everything you can pass to - * `injectInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages, from a button click or - * automatically as the user scrolls. - * @see {@link injectInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `injectInfiniteQuery`. These options can be shared across functions + * and imperative APIs such as `queryClient.fetchInfiniteQuery`. + * `options.queryKey` is required and is the query key to generate options for. + * + * @remarks + * See {@link injectInfiniteQuery} for examples that fetch further pages, from + * a button click or automatically as the user scrolls. * @example - * A parameterized factory, so the same options object can be reused per `postId`: - * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * A parameterized factory, so the same options object can be reused per `postId`: + * ```angular-ts + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' * - * export const commentsOptions = (postId: string) => + * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ - * queryKey: ['post', postId, 'comments'], - * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', postId, 'comments'], + * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * - * @Component({ + * @Component({ * selector: 'comments', * template: ` - * @if (commentsQuery.isPending()) { - * Loading... - * } @else if (commentsQuery.isError()) { - * Error: {{ commentsQuery.error()?.message }} - * } @else { - *
    - * @for (page of commentsQuery.data().pages; track $index) { - * @for (comment of page.comments; track comment.id) { - *
  • {{ comment.text }}
  • - * } - * } - *
- * } + * @if (commentsQuery.isPending()) { + * Loading... + * } @else if (commentsQuery.isError()) { + * Error: {{ commentsQuery.error()?.message }} + * } @else { + *
    + * @for (page of commentsQuery.data().pages; track $index) { + * @for (comment of page.comments; track comment.id) { + *
  • {{ comment.text }}
  • + * } + * } + *
+ * } * `, - * }) - * export class Comments { + * }) + * export class Comments { * readonly postId = signal('1') * readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId())) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UnusedSkipTokenInfiniteOptions} to use — + * everything you can pass to `injectInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -268,52 +295,57 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to - * `injectInfiniteQuery`. These options can be shared across functions and imperative APIs such as - * `queryClient.fetchInfiniteQuery`. `options.queryKey` is required and is the query key to generate options - * for. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `injectInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link injectInfiniteQuery} for examples that fetch further pages (from a button click or - * automatically as the user scrolls) and that use `skipToken` to disable the query until `postId` is set. - * @see {@link injectInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `injectInfiniteQuery`. These options can be shared across functions + * and imperative APIs such as `queryClient.fetchInfiniteQuery`. + * `options.queryKey` is required and is the query key to generate options for. + * + * @remarks + * See {@link injectInfiniteQuery} for examples that fetch further pages (from + * a button click or automatically as the user scrolls) and that use + * `skipToken` to disable the query until `postId` is set. * @example - * A parameterized factory, so the same options object can be reused per `postId`: - * ```angular-ts - * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' + * A parameterized factory, so the same options object can be reused per `postId`: + * ```angular-ts + * import { infiniteQueryOptions, injectInfiniteQuery } from '@tanstack/angular-query-experimental' * - * export const commentsOptions = (postId: string) => + * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ - * queryKey: ['post', postId, 'comments'], - * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', postId, 'comments'], + * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * - * @Component({ + * @Component({ * selector: 'comments', * template: ` - * @if (commentsQuery.isPending()) { - * Loading... - * } @else if (commentsQuery.isError()) { - * Error: {{ commentsQuery.error()?.message }} - * } @else { - *
    - * @for (page of commentsQuery.data().pages; track $index) { - * @for (comment of page.comments; track comment.id) { - *
  • {{ comment.text }}
  • - * } - * } - *
- * } + * @if (commentsQuery.isPending()) { + * Loading... + * } @else if (commentsQuery.isError()) { + * Error: {{ commentsQuery.error()?.message }} + * } @else { + *
    + * @for (page of commentsQuery.data().pages; track $index) { + * @for (comment of page.comments; track comment.id) { + *
  • {{ comment.text }}
  • + * } + * } + *
+ * } * `, - * }) - * export class Comments { + * }) + * export class Comments { * readonly postId = signal('1') * readonly commentsQuery = injectInfiniteQuery(() => commentsOptions(this.postId())) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `injectInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, diff --git a/packages/angular-query-experimental/src/inject-infinite-query.ts b/packages/angular-query-experimental/src/inject-infinite-query.ts index d48a4f25017..da9e0c8ffca 100644 --- a/packages/angular-query-experimental/src/inject-infinite-query.ts +++ b/packages/angular-query-experimental/src/inject-infinite-query.ts @@ -23,64 +23,74 @@ import type { } from './infinite-query-options' /** - * Options for `injectInfiniteQuery`, passed after the function that returns the infinite - * query options. + * Options for `injectInfiniteQuery`, passed after the function that returns the + * infinite query options. */ export interface InjectInfiniteQueryOptions { /** * The `Injector` in which to create the infinite query. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * The options for `injectInfiniteQuery` are identical to `injectQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. Infinite queries can - * additively "load more" data onto an existing set of data, or "infinite scroll". + * The options for `injectInfiniteQuery` are identical to `injectQuery`, with + * the addition of `initialPageParam`, `getNextPageParam`, + * `getPreviousPageParam`, and `maxPages`. Infinite queries can additively "load + * more" data onto an existing set of data, or "infinite scroll". * - * This overload is selected when `initialData` is set on the options returned by `injectInfiniteQueryFn`, - * so the resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). - * @param injectInfiniteQueryFn - A function returning the {@link DefinedInitialDataInfiniteOptions} to use — - * everything you can pass to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` from - * Angular, this function runs in the reactive context, so signals read inside it drive the query. - * @param options - Additional configuration. - * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and - * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage() && !isFetching()`. - * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs - * like `queryClient.fetchInfiniteQuery`. + * This overload is selected when `initialData` is set on the options returned + * by `injectInfiniteQueryFn`, so the resulting `data` signal is never + * `undefined` (unless a `select` changes `TData` to include `undefined`). + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage() && !isFetching()`. * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'projects', * template: ` - * - *
    - * @for (page of projectsQuery.data().pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
+ * + *
    + * @for (page of projectsQuery.data().pages; track $index) { + * @for (project of page.projects; track project.id) { + *
  • {{ project.name }}
  • + * } + * } + *
* `, - * }) - * export class Projects { + * }) + * export class Projects { * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, * })) - * } - * ``` + * } + * ``` + * + * @param injectInfiniteQueryFn - A function returning the + * {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass + * to `injectInfiniteQuery`, with `initialData` set. Similar to `computed` + * from Angular, this function runs in the reactive context, so signals read + * inside it drive the query. + * @param options - Additional configuration. + * @returns The same signals as `injectQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and + * `data().pageParams` are also added, as long as a `select` doesn't change + * `TData` away from its default `InfiniteData` shape. + * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs + * like `queryClient.fetchInfiniteQuery`. */ export function injectInfiniteQuery< TQueryFnData, @@ -100,139 +110,148 @@ export function injectInfiniteQuery< ): DefinedCreateInfiniteQueryResult /** - * Injects an infinite query: a declarative dependency on an asynchronous source of data that is tied to a - * unique key. Infinite queries can additively "load more" data onto an existing set of data, or - * "infinite scroll". - * @param injectInfiniteQueryFn - A function returning the {@link UndefinedInitialDataInfiniteOptions} to use - * — everything you can pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this function runs - * in the reactive context, so signals read inside it drive the query. - * @param options - Additional configuration. - * @returns The same signals as `injectQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and - * `data().pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage() && !isFetching()`. This is the only overload that accepts - * `queryFn: skipToken`, shown below. - * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs - * like `queryClient.fetchInfiniteQuery`. + * Injects an infinite query: a declarative dependency on an asynchronous source + * of data that is tied to a unique key. Infinite queries can additively "load + * more" data onto an existing set of data, or "infinite scroll". + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage() && !isFetching()`. This is the only overload + * that accepts `queryFn: skipToken`, shown below. * @example - * Fetching the next page from a button click: - * ```angular-ts - * @Component({ + * Fetching the next page from a button click: + * ```angular-ts + * @Component({ * selector: 'projects-list', * template: ` - *
    - * @for (page of projectsQuery.data()?.pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
- * + *
    + * @for (page of projectsQuery.data()?.pages; track $index) { + * @for (project of page.projects; track project.id) { + *
  • {{ project.name }}
  • + * } + * } + *
+ * * `, - * }) - * export class ProjectsList { + * }) + * export class ProjectsList { * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * })) - * } - * ``` + * } + * ``` + * * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel - * element after the list: - * ```angular-ts - * @Component({ + * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a sentinel + * element after the list: + * ```angular-ts + * @Component({ * selector: 'projects-list', * template: ` - *
    - * @for (page of projectsQuery.data()?.pages; track $index) { - * @for (project of page.projects; track project.id) { - *
  • {{ project.name }}
  • - * } - * } - *
- *
{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}
+ *
    + * @for (page of projectsQuery.data()?.pages; track $index) { + * @for (project of page.projects; track project.id) { + *
  • {{ project.name }}
  • + * } + * } + *
+ *
{{ projectsQuery.isFetchingNextPage() ? 'Loading more...' : '' }}
* `, - * }) - * export class ProjectsList { + * }) + * export class ProjectsList { * readonly sentinel = viewChild>('sentinel') * * readonly projectsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * })) * * constructor() { - * effect((onCleanup) => { - * const sentinel = this.sentinel()?.nativeElement - * if ( - * sentinel == null || - * !this.projectsQuery.hasNextPage() || - * this.projectsQuery.isFetching() - * ) { - * return - * } + * effect((onCleanup) => { + * const sentinel = this.sentinel()?.nativeElement + * if ( + * sentinel == null || + * !this.projectsQuery.hasNextPage() || + * this.projectsQuery.isFetching() + * ) { + * return + * } * - * const observer = new IntersectionObserver(([entry]) => { - * if (entry?.isIntersecting) this.projectsQuery.fetchNextPage() - * }) - * observer.observe(sentinel) + * const observer = new IntersectionObserver(([entry]) => { + * if (entry?.isIntersecting) this.projectsQuery.fetchNextPage() + * }) + * observer.observe(sentinel) * - * onCleanup(() => observer.disconnect()) - * }) + * onCleanup(() => observer.disconnect()) + * }) + * } * } - * } - * ``` + * ``` + * * @example - * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of - * setting `enabled: false`: - * ```angular-ts - * @Component({ + * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` instead of + * setting `enabled: false`: + * ```angular-ts + * @Component({ * selector: 'comments', * template: ` - * @if (postId() == null) { - * Select a post - * } @else if (commentsQuery.isPending()) { - * Loading... - * } @else if (commentsQuery.isError()) { - * Error: {{ commentsQuery.error()?.message }} - * } @else { - *
    - * @for (page of commentsQuery.data().pages; track $index) { - * @for (comment of page.comments; track comment.id) { - *
  • {{ comment.text }}
  • - * } - * } - *
- * } + * @if (postId() == null) { + * Select a post + * } @else if (commentsQuery.isPending()) { + * Loading... + * } @else if (commentsQuery.isError()) { + * Error: {{ commentsQuery.error()?.message }} + * } @else { + *
    + * @for (page of commentsQuery.data().pages; track $index) { + * @for (comment of page.comments; track comment.id) { + *
  • {{ comment.text }}
  • + * } + * } + *
+ * } * `, - * }) - * export class Comments { + * }) + * export class Comments { * readonly postId = signal(undefined) * * readonly commentsQuery = injectInfiniteQuery(() => ({ - * queryKey: ['post', this.postId(), 'comments'], - * queryFn: - * this.postId() != null - * ? ({ pageParam }) => fetchComments(this.postId()!, pageParam) - * : skipToken, - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', this.postId(), 'comments'], + * queryFn: + * this.postId() != null + * ? ({ pageParam }) => fetchComments(this.postId()!, pageParam) + * : skipToken, + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * })) - * } - * ``` + * } + * ``` + * + * @param injectInfiniteQueryFn - A function returning the + * {@link UndefinedInitialDataInfiniteOptions} to use — everything you can + * pass to `injectInfiniteQuery`. Similar to `computed` from Angular, this + * function runs in the reactive context, so signals read inside it drive the + * query. + * @param options - Additional configuration. + * @returns The same signals as `injectQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data().pages` and + * `data().pageParams` are also added, as long as a `select` doesn't change + * `TData` away from its default `InfiniteData` shape. + * @see {@link infiniteQueryOptions} to share these options between `injectInfiniteQuery` and imperative APIs + * like `queryClient.fetchInfiniteQuery`. */ export function injectInfiniteQuery< TQueryFnData, @@ -252,12 +271,15 @@ export function injectInfiniteQuery< ): CreateInfiniteQueryResult /** - * This overload accepts the general {@link CreateInfiniteQueryOptions} shape rather than the - * `initialData`-aware overloads above, so whether `data` is defined can't be inferred from the call site — - * useful when wrapping `injectInfiniteQuery` in your own helper function that forwards caller-provided - * options. - * @param injectInfiniteQueryFn - A function that returns infinite query options. Similar to `computed` from - * Angular, this function runs in the reactive context, so signals read inside it drive the query. + * This overload accepts the general {@link CreateInfiniteQueryOptions} shape + * rather than the `initialData`-aware overloads above, so whether `data` is + * defined can't be inferred from the call site — useful when wrapping + * `injectInfiniteQuery` in your own helper function that forwards + * caller-provided options. + * + * @param injectInfiniteQueryFn - A function that returns infinite query + * options. Similar to `computed` from Angular, this function runs in the + * reactive context, so signals read inside it drive the query. * @param options - Additional configuration. * @returns The infinite query result. */ diff --git a/packages/angular-query-experimental/src/inject-is-fetching.ts b/packages/angular-query-experimental/src/inject-is-fetching.ts index 54b6f289e3d..32cd79a4f98 100644 --- a/packages/angular-query-experimental/src/inject-is-fetching.ts +++ b/packages/angular-query-experimental/src/inject-is-fetching.ts @@ -10,55 +10,58 @@ import { QueryClient, notifyManager } from '@tanstack/query-core' import type { QueryFilters } from '@tanstack/query-core' import type { Signal } from '@angular/core' -/** - * Options for `injectIsFetching`, passed after the query filters. - */ +/** Options for `injectIsFetching`, passed after the query filters. */ export interface InjectIsFetchingOptions { /** * The `Injector` in which to create the isFetching signal. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * Injects a signal that tracks the number of queries that your application is loading or fetching in the - * background (useful for app-wide loading indicators). - * @param filters - The {@link QueryFilters} to narrow down the matched queries. - * @param options - Additional configuration - * @returns A `Signal` with the number of queries that your application is currently loading or fetching in - * the background. + * Injects a signal that tracks the number of queries that your application is + * loading or fetching in the background (useful for app-wide loading + * indicators). + * * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'posts-fetching-indicator', * template: ` - * @if (isFetchingPosts()) { - * Refreshing posts... - * } + * @if (isFetchingPosts()) { + * Refreshing posts... + * } * `, - * }) - * export class PostsFetchingIndicator { + * }) + * export class PostsFetchingIndicator { * // How many queries matching the posts prefix are fetching? * readonly isFetchingPosts = injectIsFetching({ queryKey: ['posts'] }) - * } - * ``` + * } + * ``` + * * @example - * A global loading indicator for any query fetching in the background, not just the ones on screen: - * ```angular-ts - * @Component({ + * A global loading indicator for any query fetching in the background, not just the ones on screen: + * ```angular-ts + * @Component({ * selector: 'global-loading-indicator', * template: ` - * @if (isFetching()) { - *
Queries are fetching in the background...
- * } + * @if (isFetching()) { + *
Queries are fetching in the background...
+ * } * `, - * }) - * export class GlobalLoadingIndicator { + * }) + * export class GlobalLoadingIndicator { * readonly isFetching = injectIsFetching() - * } - * ``` + * } + * ``` + * + * @param filters - The {@link QueryFilters} to narrow down the matched queries. + * @param options - Additional configuration + * @returns A `Signal` with the number of queries that your application is + * currently loading or fetching in the background. */ export function injectIsFetching( filters?: QueryFilters, diff --git a/packages/angular-query-experimental/src/inject-is-mutating.ts b/packages/angular-query-experimental/src/inject-is-mutating.ts index d6e9e008cda..517fd03ee48 100644 --- a/packages/angular-query-experimental/src/inject-is-mutating.ts +++ b/packages/angular-query-experimental/src/inject-is-mutating.ts @@ -10,39 +10,42 @@ import { QueryClient, notifyManager } from '@tanstack/query-core' import type { MutationFilters } from '@tanstack/query-core' import type { Signal } from '@angular/core' -/** - * Options for `injectIsMutating`, passed after the mutation filters. - */ +/** Options for `injectIsMutating`, passed after the mutation filters. */ export interface InjectIsMutatingOptions { /** * The `Injector` in which to create the isMutating signal. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * Injects a signal that tracks the number of mutations that your application currently has `pending` - * (useful for app-wide loading indicators). - * @param filters - The {@link MutationFilters} to narrow down the matched mutations. - * @param options - Additional configuration - * @returns A `Signal` with the number of mutations that your application currently has `pending`. + * Injects a signal that tracks the number of mutations that your application + * currently has `pending` (useful for app-wide loading indicators). + * * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'posts-mutating-indicator', * template: ` - * @if (isMutatingPosts()) { - * Saving posts... - * } + * @if (isMutatingPosts()) { + * Saving posts... + * } * `, - * }) - * export class PostsMutatingIndicator { + * }) + * export class PostsMutatingIndicator { * // How many mutations matching the posts prefix are in progress? * readonly isMutatingPosts = injectIsMutating({ mutationKey: ['posts'] }) - * } - * ``` + * } + * ``` + * + * @param filters - The {@link MutationFilters} to narrow down the matched + * mutations. + * @param options - Additional configuration + * @returns A `Signal` with the number of mutations that your application + * currently has `pending`. */ export function injectIsMutating( filters?: MutationFilters, diff --git a/packages/angular-query-experimental/src/inject-is-restoring.ts b/packages/angular-query-experimental/src/inject-is-restoring.ts index 901f5e55852..5e88bcba3b1 100644 --- a/packages/angular-query-experimental/src/inject-is-restoring.ts +++ b/packages/angular-query-experimental/src/inject-is-restoring.ts @@ -8,7 +8,8 @@ import { import type { Provider, Signal } from '@angular/core' /** - * Internal token used to track isRestoring state, accessible in public API through `injectIsRestoring` and set via `provideIsRestoring` + * Internal token used to track isRestoring state, accessible in public API + * through `injectIsRestoring` and set via `provideIsRestoring` */ const IS_RESTORING = new InjectionToken('', { // Default value when not provided @@ -19,18 +20,22 @@ interface InjectIsRestoringOptions { /** * The `Injector` to use to get the isRestoring signal. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * Injects a signal that tracks whether a restore (e.g. from a persisted client, wired up via - * `provideIsRestoring`) is currently in progress. `injectQuery` and friends also check this internally to - * avoid race conditions between the restore and initializing queries. + * Injects a signal that tracks whether a restore (e.g. from a persisted client, + * wired up via `provideIsRestoring`) is currently in progress. `injectQuery` + * and friends also check this internally to avoid race conditions between the + * restore and initializing queries. + * * @param options - Additional configuration - * @returns A readonly `Signal` — `true` while a restore is in progress, `false` otherwise (the - * default when no `provideIsRestoring` provider is registered). + * @returns A readonly `Signal` — `true` while a restore is in + * progress, `false` otherwise (the default when no `provideIsRestoring` + * provider is registered). */ export function injectIsRestoring(options?: InjectIsRestoringOptions) { !options?.injector && assertInInjectionContext(injectIsRestoring) @@ -39,10 +44,14 @@ export function injectIsRestoring(options?: InjectIsRestoringOptions) { } /** - * Registers a provider for the restore state read by `injectIsRestoring`. Wire this up wherever you drive a - * restore yourself — e.g. a persist-client integration — so `injectQuery` and friends can defer subscribing - * to their observer (avoiding a race with the restore) until the restore signal flips back to `false`. - * @param isRestoring - A readonly `Signal` that tracks the restore state. + * Registers a provider for the restore state read by `injectIsRestoring`. Wire + * this up wherever you drive a restore yourself — e.g. a persist-client + * integration — so `injectQuery` and friends can defer subscribing to their + * observer (avoiding a race with the restore) until the restore signal flips + * back to `false`. + * + * @param isRestoring - A readonly `Signal` that tracks the restore + * state. * @returns A provider for the `isRestoring` signal. */ export function provideIsRestoring(isRestoring: Signal): Provider { diff --git a/packages/angular-query-experimental/src/inject-mutation-state.ts b/packages/angular-query-experimental/src/inject-mutation-state.ts index 1396125281a..7f2e4eee6af 100644 --- a/packages/angular-query-experimental/src/inject-mutation-state.ts +++ b/packages/angular-query-experimental/src/inject-mutation-state.ts @@ -26,10 +26,12 @@ type MutationStateOptions = { } /** - * Collects the mutations in the cache that match `options.filters`, mapped with `options.select` - * (or to their state, by default). + * Collects the mutations in the cache that match `options.filters`, mapped with + * `options.select` (or to their state, by default). + * * @param mutationCache - The mutation cache to read. - * @param options - The `filters` to match and the `select` function to map each mutation with. + * @param options - The `filters` to match and the `select` function to map each + * mutation with. * @returns The selected value of every matching mutation. */ function getResult( @@ -45,71 +47,79 @@ function getResult( } /** - * Options for `injectMutationState`, passed after the function that returns the mutation state - * options. + * Options for `injectMutationState`, passed after the function that returns the + * mutation state options. */ export interface InjectMutationStateOptions { /** * The `Injector` in which to create the mutation state signal. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * Injects a signal that gives you access to all mutations in the `MutationCache`. You can pass `filters` - * ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the mutation state. - * @param injectMutationStateFn - A function returning the `filters` to narrow down matched mutations, and an - * optional `select` to transform the mutation state. Similar to `computed` from Angular, this function runs - * in the reactive context, so signals read inside it re-narrow the matched mutations. - * @param options - Additional configuration - * @returns A `Signal` with an Array of whatever `select` returns for each matching mutation. + * Injects a signal that gives you access to all mutations in the + * `MutationCache`. You can pass `filters` ({@link MutationFilters}) to narrow + * down your mutations, and `select` to transform the mutation state. + * * @example - * Get all variables of all running mutations: - * ```angular-ts - * @Component({ + * Get all variables of all running mutations: + * ```angular-ts + * @Component({ * selector: 'pending-posts', * template: `{{ pendingVariables().length }} posts saving...`, - * }) - * export class PendingPosts { + * }) + * export class PendingPosts { * readonly pendingVariables = injectMutationState(() => ({ - * filters: { status: 'pending' }, - * select: (mutation) => mutation.state.variables, + * filters: { status: 'pending' }, + * select: (mutation) => mutation.state.variables, * })) - * } - * ``` + * } + * ``` + * * @example - * Get all data for specific mutations via the `mutationKey`: - * ```angular-ts - * const mutationKey = ['posts'] + * Get all data for specific mutations via the `mutationKey`: + * ```angular-ts + * const mutationKey = ['posts'] * - * @Component({ + * @Component({ * selector: 'posts', * template: ` - * + * * `, - * }) - * export class Posts { + * }) + * export class Posts { * // Some mutation that we want to get the state for * readonly createPostMutation = injectMutation(() => ({ - * mutationKey, - * mutationFn: createPosts, + * mutationKey, + * mutationFn: createPosts, * })) * * readonly savedPosts = injectMutationState(() => ({ - * // this mutation key needs to match the mutation key of the given mutation (see above) - * filters: { mutationKey, status: 'success' }, - * select: (mutation) => mutation.state.data, + * // this mutation key needs to match the mutation key of the given mutation (see above) + * filters: { mutationKey, status: 'success' }, + * select: (mutation) => mutation.state.data, * })) * * createPost() { - * this.createPostMutation.mutate(['New Post']) + * this.createPostMutation.mutate(['New Post']) * } - * } - * ``` + * } + * ``` + * + * @param injectMutationStateFn - A function returning the `filters` to narrow + * down matched mutations, and an optional `select` to transform the mutation + * state. Similar to `computed` from Angular, this function runs in the + * reactive context, so signals read inside it re-narrow the matched + * mutations. + * @param options - Additional configuration + * @returns A `Signal` with an Array of whatever `select` returns for each + * matching mutation. */ export function injectMutationState( injectMutationStateFn: () => MutationStateOptions = () => ({}), @@ -123,8 +133,9 @@ export function injectMutationState( const mutationCache = queryClient.getMutationCache() /** - * Computed signal that gets result from mutation cache based on passed options - * First element is the result, second element is the time when the result was set + * Computed signal that gets result from mutation cache based on passed + * options First element is the result, second element is the time when the + * result was set */ const resultFromOptionsSignal = computed(() => { return [ @@ -134,16 +145,14 @@ export function injectMutationState( }) /** - * Signal that contains result set by subscriber - * First element is the result, second element is the time when the result was set + * Signal that contains result set by subscriber First element is the result, + * second element is the time when the result was set */ const resultFromSubscriberSignal = signal<[Array, number] | null>( null, ) - /** - * Returns the last result by either subscriber or options - */ + /** Returns the last result by either subscriber or options */ const effectiveResultSignal = computed(() => { const optionsResult = resultFromOptionsSignal() const subscriberResult = resultFromSubscriberSignal() diff --git a/packages/angular-query-experimental/src/inject-mutation.ts b/packages/angular-query-experimental/src/inject-mutation.ts index 0557ec2c821..384833189ef 100644 --- a/packages/angular-query-experimental/src/inject-mutation.ts +++ b/packages/angular-query-experimental/src/inject-mutation.ts @@ -26,148 +26,162 @@ import type { } from './types' /** - * Options for `injectMutation`, passed after the function that returns the mutation options. + * Options for `injectMutation`, passed after the function that returns the + * mutation options. */ export interface InjectMutationOptions { /** * The `Injector` in which to create the mutation. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. - * `injectMutation` is the function for that. Unlike queries, mutations are not run automatically. - * @param injectMutationFn - A function that returns mutation options. Similar to `computed` from Angular, - * this function runs in the reactive context, so signals read inside it drive the mutation's options. - * @param options - Additional configuration - * @returns The mutation result. Value fields are exposed as a `Signal` — read `data`/`error` by calling them - * (e.g. `mutation.data()`) — while function fields (`mutate`, `mutateAsync`, `reset`) are called directly, - * unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can call to narrow whether - * `data` is defined. - * @remarks `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a - * second argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to - * the shared mutation definition. Callbacks defined in `injectMutationFn` fire for every mutation; per-call - * callbacks fire only for the latest call you've made — `mutateAsync` gives you a promise per call instead, - * so you can await `Promise.all`/`Promise.allSettled` over several calls and see each one's outcome. - * @see {@link mutationOptions} to share these options across multiple `injectMutation` call sites, or to look - * the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`). + * Unlike queries, mutations are typically used to create/update/delete data or + * perform server side-effects. `injectMutation` is the function for that. + * Unlike queries, mutations are not run automatically. + * + * @remarks + * `mutate`/`mutateAsync` also accept per-call + * `onSuccess`/`onError`/`onSettled` callbacks as a second argument, useful + * for triggering call-site side effects (e.g. navigation) without coupling + * them to the shared mutation definition. Callbacks defined in + * `injectMutationFn` fire for every mutation; per-call callbacks fire only + * for the latest call you've made — `mutateAsync` gives you a promise per + * call instead, so you can await `Promise.all`/`Promise.allSettled` over + * several calls and see each one's outcome. * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'todos', * template: ` - * @if (addMutation.isPending()) { - * Adding todo... - * } @else if (addMutation.isError()) { - *
An error occurred: {{ addMutation.error()?.message }}
- * } - * + * @if (addMutation.isPending()) { + * Adding todo... + * } @else if (addMutation.isError()) { + *
An error occurred: {{ addMutation.error()?.message }}
+ * } + * * `, - * }) - * export class Todos { + * }) + * export class Todos { * readonly #queryClient = inject(QueryClient) * * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), * })) - * } - * ``` + * } + * ``` + * * @example - * Optimistic update via `onMutate`, rolling back on `onError`: - * ```angular-ts - * @Component({ + * Optimistic update via `onMutate`, rolling back on `onError`: + * ```angular-ts + * @Component({ * selector: 'todos', * template: ``, - * }) - * export class Todos { + * }) + * export class Todos { * readonly #queryClient = inject(QueryClient) * * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onMutate: async (newTodo) => { - * await this.#queryClient.cancelQueries({ queryKey: ['todos'] }) - * const previousTodos = this.#queryClient.getQueryData>(['todos']) + * mutationFn: addTodo, + * onMutate: async (newTodo) => { + * await this.#queryClient.cancelQueries({ queryKey: ['todos'] }) + * const previousTodos = this.#queryClient.getQueryData>(['todos']) * - * this.#queryClient.setQueryData>(['todos'], (old) => [ - * ...(old ?? []), - * newTodo, - * ]) + * this.#queryClient.setQueryData>(['todos'], (old) => [ + * ...(old ?? []), + * newTodo, + * ]) * - * // Passed to `onError` as `onMutateResult` if the mutation fails. - * return { previousTodos } - * }, - * onError: (_err, _newTodo, onMutateResult) => { - * this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) - * }, - * onSettled: () => { - * this.#queryClient.invalidateQueries({ queryKey: ['todos'] }) - * }, + * // Passed to `onError` as `onMutateResult` if the mutation fails. + * return { previousTodos } + * }, + * onError: (_err, _newTodo, onMutateResult) => { + * this.#queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) + * }, + * onSettled: () => { + * this.#queryClient.invalidateQueries({ queryKey: ['todos'] }) + * }, * })) - * } - * ``` + * } + * ``` + * * @example - * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per - * call instead, so you can wait for all of them when they succeed: - * ```angular-ts - * @Component({ + * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a promise per + * call instead, so you can wait for all of them when they succeed: + * ```angular-ts + * @Component({ * selector: 'todos', * template: ` - * + * * `, - * }) - * export class Todos { + * }) + * export class Todos { * readonly #queryClient = inject(QueryClient) * * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), * })) * * async handleAddAll(todos: Array) { - * try { - * await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo))) - * } catch (error) { - * console.error('Failed to add todos:', error) - * } + * try { + * await Promise.all(todos.map((todo) => this.addMutation.mutateAsync(todo))) + * } catch (error) { + * console.error('Failed to add todos:', error) + * } * } - * } - * ``` + * } + * ``` + * * @example - * If some of the mutations above can fail independently of the others, and you want to know which ones did — - * rather than losing that information the moment the first one rejects — swap `Promise.all` for - * `Promise.allSettled`: - * ```angular-ts - * @Component({ + * If some of the mutations above can fail independently of the others, and you want to know which ones did — + * rather than losing that information the moment the first one rejects — swap `Promise.all` for + * `Promise.allSettled`: + * ```angular-ts + * @Component({ * selector: 'todos', * template: ` - * + * * `, - * }) - * export class Todos { + * }) + * export class Todos { * readonly #queryClient = inject(QueryClient) * * readonly addMutation = injectMutation(() => ({ - * mutationFn: addTodo, - * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => this.#queryClient.invalidateQueries({ queryKey: ['todos'] }), * })) * * async handleAddAll(todos: Array) { - * const addResults = await Promise.allSettled( - * todos.map((todo) => this.addMutation.mutateAsync(todo)), - * ) + * const addResults = await Promise.allSettled( + * todos.map((todo) => this.addMutation.mutateAsync(todo)), + * ) * - * addResults.forEach((addResult, index) => { - * if (addResult.status === 'rejected') { - * console.error(`Failed to add "${todos[index]}":`, addResult.reason) - * } - * }) + * addResults.forEach((addResult, index) => { + * if (addResult.status === 'rejected') { + * console.error(`Failed to add "${todos[index]}":`, addResult.reason) + * } + * }) * } - * } - * ``` + * } + * ``` + * + * @param injectMutationFn - A function that returns mutation options. Similar + * to `computed` from Angular, this function runs in the reactive context, so + * signals read inside it drive the mutation's options. + * @param options - Additional configuration + * @returns The mutation result. Value fields are exposed as a `Signal` — read + * `data`/`error` by calling them (e.g. `mutation.data()`) — while function + * fields (`mutate`, `mutateAsync`, `reset`) are called directly, unchanged. + * `isSuccess`/`isError`/`isPending`/`isIdle` are type-guard methods you can + * call to narrow whether `data` is defined. + * @see {@link mutationOptions} to share these options across multiple `injectMutation` call sites, or to look + * the mutation up elsewhere via its `mutationKey` (e.g. with `injectMutationState`). */ export function injectMutation< TData = unknown, @@ -190,9 +204,9 @@ export function injectMutation< const queryClient = injector.get(QueryClient) /** - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes + * Computed() is used so signals can be inserted into the options making it + * reactive. Wrapping options in a function ensures embedded expressions are + * preserved and can keep being applied after signal changes */ const optionsSignal = computed(injectMutationFn) @@ -223,16 +237,15 @@ export function injectMutation< }) /** - * Computed signal that gets result from mutation cache based on passed options + * Computed signal that gets result from mutation cache based on passed + * options */ const resultFromInitialOptionsSignal = computed(() => { const observer = observerSignal() return observer.getCurrentResult() }) - /** - * Signal that contains result set by subscriber - */ + /** Signal that contains result set by subscriber */ const resultFromSubscriberSignal = signal = CreateQueryResult /** - * The `queries` array accepted by `injectQueries`. Recursively unwraps each tuple element so every entry's - * `queryFn`/`select`/`throwOnError` are inferred individually, up to 20 elements — past that, tuple - * recursion falls back to a single homogeneous options type. An opaque array (e.g. `unknown[]`) is returned - * as-is; a non-tuple array of a known element type is mapped to that element type instead, with no such - * limit. + * The `queries` array accepted by `injectQueries`. Recursively unwraps each + * tuple element so every entry's `queryFn`/`select`/`throwOnError` are inferred + * individually, up to 20 elements — past that, tuple recursion falls back to a + * single homogeneous options type. An opaque array (e.g. `unknown[]`) is + * returned as-is; a non-tuple array of a known element type is mapped to that + * element type instead, with no such limit. + * * @template T - The type of the `queries` array as written at the call site. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant to - * be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type QueriesOptions< T extends Array, @@ -190,15 +192,19 @@ export type QueriesOptions< Array /** - * The result type returned by `injectQueries`, when no `combine` is provided. Mirrors {@link QueriesOptions}: - * each tuple element's result type is inferred individually, up to 20 elements — past that, tuple recursion - * falls back to a single homogeneous {@link CreateQueryResult} type. A non-tuple array is mapped per-element - * instead, with no such limit — every entry keeps its individually inferred type regardless of array length. - * @template T - The type of the `queries` array, as inferred by {@link QueriesOptions}. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant to - * be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * The result type returned by `injectQueries`, when no `combine` is provided. + * Mirrors {@link QueriesOptions}: each tuple element's result type is inferred + * individually, up to 20 elements — past that, tuple recursion falls back to a + * single homogeneous {@link CreateQueryResult} type. A non-tuple array is mapped + * per-element instead, with no such limit — every entry keeps its individually + * inferred type regardless of array length. + * + * @template T - The type of the `queries` array, as inferred by + * {@link QueriesOptions}. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type QueriesResults< T extends Array, @@ -219,24 +225,22 @@ export type QueriesResults< : { [K in keyof T]: GetCreateQueryResult } /** - * The options for `injectQueries`: the `queries` to run, and an optional `combine` function that - * derives a single result from all the query results. + * The options for `injectQueries`: the `queries` to run, and an optional + * `combine` function that derives a single result from all the query results. */ export interface InjectQueriesOptions< T extends Array, TCombinedResult = QueriesResults, > { - /** - * The array of query options to run, one query per element. - */ + /** The array of query options to run, one query per element. */ queries: | readonly [...QueriesOptions] | readonly [ ...{ [K in keyof T]: GetCreateQueryOptionsForCreateQueries }, ] /** - * Combines the results of all the queries into a single value, which `injectQueries` returns - * instead of the results array. + * Combines the results of all the queries into a single value, which + * `injectQueries` returns instead of the results array. */ combine?: (result: QueriesResults) => TCombinedResult } @@ -244,132 +248,144 @@ export interface InjectQueriesOptions< /** * Injects a signal to fetch a variable number of queries. * - * The `queries` key accepts an array with query option objects mostly identical to `injectQuery`'s. Having - * the same query key more than once in the array of query objects may cause some data to be shared between - * queries. To avoid this, consider de-duplicating the queries and map the results back to the desired - * structure. + * The `queries` key accepts an array with query option objects mostly identical + * to `injectQuery`'s. Having the same query key more than once in the array of + * query objects may cause some data to be shared between queries. To avoid + * this, consider de-duplicating the queries and map the results back to the + * desired structure. + * + * The `combine` option can be used to combine the results of the queries into a + * single value. The result will be structurally shared to be as referentially + * stable as possible. * - * The `combine` option can be used to combine the results of the queries into a single value. The result - * will be structurally shared to be as referentially stable as possible. - * @param optionsFn - A function returning the queries' options — an array of query option objects under - * `queries`, and an optional `combine`. Similar to `computed` from Angular, this function runs in the - * reactive context, so signals read inside it (e.g. to build the `queries` array) drive the queries. - * @param injector - The `Injector` in which to create the queries. If this is not provided, the current - * injection context will be used instead (via `inject`). - * @returns A `Signal` with the combined result. Without `combine`, this is an array with all the query - * results, in the same order as the input. When `combine` is provided, this is the value returned by - * `combine` instead. - * @remarks Unlike `injectQuery`, `injectQueries` cannot infer the `data` argument of an _inline_ `select` - * from its sibling `queryFn`. Because `injectQueries` infers the type of the whole `queries` array at once, - * the `select` parameter of a query object written inline cannot be contextually typed from that same - * object's `queryFn`, so it falls back to `unknown` — a - * [known TypeScript limitation](https://github.com/TanStack/query/issues/6556). Annotate the `select` - * parameter explicitly, or define the query with {@link queryOptions}, which resolves its types in a single - * object _before_ it reaches `injectQueries`, to work around this — see the example below. + * @remarks + * Unlike `injectQuery`, `injectQueries` cannot infer the `data` argument of + * an _inline_ `select` from its sibling `queryFn`. Because `injectQueries` + * infers the type of the whole `queries` array at once, the `select` + * parameter of a query object written inline cannot be contextually typed + * from that same object's `queryFn`, so it falls back to `unknown` — a [known + * TypeScript limitation](https://github.com/TanStack/query/issues/6556). + * Annotate the `select` parameter explicitly, or define the query with + * {@link queryOptions}, which resolves its types in a single object _before_ + * it reaches `injectQueries`, to work around this — see the example below. * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'posts', * template: ` - *
    - * @for (query of postQueries(); track $index) { - * @if (query.isPending()) { - *
  • Loading...
  • - * } @else if (query.isError()) { - *
  • Error: {{ query.error()?.message }}
  • - * } @else { - *
  • {{ query.data().title }}
  • - * } - * } - *
+ *
    + * @for (query of postQueries(); track $index) { + * @if (query.isPending()) { + *
  • Loading...
  • + * } @else if (query.isError()) { + *
  • Error: {{ query.error()?.message }}
  • + * } @else { + *
  • {{ query.data().title }}
  • + * } + * } + *
* `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly ids = signal([1, 2, 3]) * * readonly postQueries = injectQueries(() => ({ - * queries: this.ids().map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * staleTime: Infinity, - * })), + * queries: this.ids().map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * staleTime: Infinity, + * })), * })) - * } - * ``` + * } + * ``` + * * @example - * Combining results into a single value: - * ```angular-ts - * @Component({ + * Combining results into a single value: + * ```angular-ts + * @Component({ * selector: 'posts', * template: ` - * @if (combined().isPending) { - * Loading... - * } @else if (combined().isError) { - * Error loading posts - * } @else { - *
    - * @for (post of combined().data; track post?.id) { - *
  • {{ post?.title }}
  • - * } - *
- * } + * @if (combined().isPending) { + * Loading... + * } @else if (combined().isError) { + * Error loading posts + * } @else { + *
    + * @for (post of combined().data; track post?.id) { + *
  • {{ post?.title }}
  • + * } + *
+ * } * `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly ids = signal([1, 2, 3]) * * readonly combined = injectQueries(() => ({ - * queries: this.ids().map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * })), - * combine: (postQueries) => ({ - * data: postQueries.map((query) => query.data), - * isPending: postQueries.some((query) => query.isPending), - * isError: postQueries.some((query) => query.isError), - * }), + * queries: this.ids().map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * })), + * combine: (postQueries) => ({ + * data: postQueries.map((query) => query.data), + * isPending: postQueries.some((query) => query.isPending), + * isError: postQueries.some((query) => query.isError), + * }), * })) - * } - * ``` + * } + * ``` + * * @example - * Typing `select` via {@link queryOptions}. Note that spreading a `queryOptions` result and overriding - * `select` inline still falls back to `unknown` — wrap the spread in `queryOptions` again so the override is - * resolved before it reaches `injectQueries`: - * ```angular-ts - * const postOptions = (id: number) => + * Typing `select` via {@link queryOptions}. Note that spreading a `queryOptions` result and overriding + * `select` inline still falls back to `unknown` — wrap the spread in `queryOptions` again so the override is + * resolved before it reaches `injectQueries`: + * ```angular-ts + * const postOptions = (id: number) => * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), * }) * - * @Component({ + * @Component({ * selector: 'post-title', * template: `

{{ fixed()[0].data() }}

`, - * }) - * export class PostTitle { + * }) + * export class PostTitle { * readonly id = signal(1) * * readonly broken = injectQueries(() => ({ - * queries: [ - * { - * ...postOptions(this.id()), - * // ❌ `data` is `unknown` here - * select: (data) => data.title, - * }, - * ], + * queries: [ + * { + * ...postOptions(this.id()), + * // ❌ `data` is `unknown` here + * select: (data) => data.title, + * }, + * ], * })) * * readonly fixed = injectQueries(() => ({ - * queries: [ - * queryOptions({ - * ...postOptions(this.id()), - * // ✅ `data` is `Post` - * select: (data) => data.title, - * }), - * ], + * queries: [ + * queryOptions({ + * ...postOptions(this.id()), + * // ✅ `data` is `Post` + * select: (data) => data.title, + * }), + * ], * })) - * } - * ``` + * } + * ``` + * + * @param optionsFn - A function returning the queries' options — an array of + * query option objects under `queries`, and an optional `combine`. Similar to + * `computed` from Angular, this function runs in the reactive context, so + * signals read inside it (e.g. to build the `queries` array) drive the + * queries. + * @param injector - The `Injector` in which to create the queries. If this is + * not provided, the current injection context will be used instead (via + * `inject`). + * @returns A `Signal` with the combined result. Without `combine`, this is an + * array with all the query results, in the same order as the input. When + * `combine` is provided, this is the value returned by `combine` instead. */ export function injectQueries< T extends Array, @@ -386,10 +402,10 @@ export function injectQueries< const isRestoring = injectIsRestoring() /** - * Signal that has the default options from query client applied - * computed() is used so signals can be inserted into the options - * making it reactive. Wrapping options in a function ensures embedded expressions - * are preserved and can keep being applied after signal changes + * Signal that has the default options from query client applied computed() + * is used so signals can be inserted into the options making it reactive. + * Wrapping options in a function ensures embedded expressions are preserved + * and can keep being applied after signal changes */ const optionsSignal = computed(() => { return optionsFn() diff --git a/packages/angular-query-experimental/src/inject-query-client.ts b/packages/angular-query-experimental/src/inject-query-client.ts index 7cd29e38508..86aae9873af 100644 --- a/packages/angular-query-experimental/src/inject-query-client.ts +++ b/packages/angular-query-experimental/src/inject-query-client.ts @@ -4,8 +4,7 @@ import type { InjectOptions } from '@angular/core' /** * Injects a `QueryClient` instance and allows passing a custom injector. - * @param injectOptions - Type of the options argument to inject and optionally a custom injector. - * @returns The `QueryClient` instance. + * * @deprecated Use `inject(QueryClient)` instead. * If you need to get a `QueryClient` from a custom injector, use `injector.get(QueryClient)`. * @@ -14,6 +13,9 @@ import type { InjectOptions } from '@angular/core' * ```ts * const queryClient = injectQueryClient(); * ``` + * @param injectOptions - Type of the options argument to inject and optionally + * a custom injector. + * @returns The `QueryClient` instance. */ export function injectQueryClient( injectOptions: InjectOptions & { injector?: Injector } = {}, diff --git a/packages/angular-query-experimental/src/inject-query.ts b/packages/angular-query-experimental/src/inject-query.ts index 6b3b3d63d82..2c05163f723 100644 --- a/packages/angular-query-experimental/src/inject-query.ts +++ b/packages/angular-query-experimental/src/inject-query.ts @@ -18,54 +18,61 @@ import type { } from './query-options' /** - * Options for `injectQuery`, passed after the function that returns the query options. + * Options for `injectQuery`, passed after the function that returns the query + * options. */ export interface InjectQueryOptions { /** * The `Injector` in which to create the query. * - * If this is not provided, the current injection context will be used instead (via `inject`). + * If this is not provided, the current injection context will be used instead + * (via `inject`). */ injector?: Injector } /** - * This overload is selected when `initialData` is set on the options returned by `injectQueryFn`, so the - * resulting `data` signal is never `undefined` (unless a `select` changes `TData` to include `undefined`). - * @param injectQueryFn - A function returning the {@link DefinedInitialDataOptions} to use — everything you - * can pass to `injectQuery`, with `initialData` set. Similar to `computed` from Angular, this function runs - * in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - * @param options - Additional configuration - * @returns The query result, typed so that `data` is never `undefined` (unless a `select` changes `TData` to - * include `undefined`). - * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries - * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like - * `queryClient.fetchQuery`. + * This overload is selected when `initialData` is set on the options returned + * by `injectQueryFn`, so the resulting `data` signal is never `undefined` + * (unless a `select` changes `TData` to include `undefined`). + * * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'posts', * template: ` - * - * @if (postsQuery.isError()) { - * Error: {{ postsQuery.error()?.message }} - * } - *
    - * @for (post of postsQuery.data(); track post.id) { - *
  • {{ post.title }}
  • - * } - *
+ * + * @if (postsQuery.isError()) { + * Error: {{ postsQuery.error()?.message }} + * } + *
    + * @for (post of postsQuery.data(); track post.id) { + *
  • {{ post.title }}
  • + * } + *
* `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly postsQuery = injectQuery(() => ({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], * })) - * } - * ``` + * } + * ``` + * + * @param injectQueryFn - A function returning the + * {@link DefinedInitialDataOptions} to use — everything you can pass to + * `injectQuery`, with `initialData` set. Similar to `computed` from Angular, + * this function runs in the reactive context, so signals read inside it (in + * `queryKey`, `enabled`, etc.) drive the query. + * @param options - Additional configuration + * @returns The query result, typed so that `data` is never `undefined` (unless + * a `select` changes `TData` to include `undefined`). + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries + * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like + * `queryClient.fetchQuery`. */ export function injectQuery< TQueryFnData = unknown, @@ -83,75 +90,82 @@ export function injectQuery< ): DefinedCreateQueryResult /** - * Injects a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. - * @param injectQueryFn - A function returning the {@link UndefinedInitialDataOptions} to use — everything - * you can pass to `injectQuery`. Similar to `computed` from Angular, this function runs in the reactive - * context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. - * @param options - Additional configuration - * @returns The query result. `status()` is `'pending'` if there is no cached data to display, `'error'` if - * the last fetch attempt failed, or `'success'` if the query has data to display. `isPending`/`isSuccess`/ - * `isError` are type-guard methods for convenience. - * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries - * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like - * `queryClient.fetchQuery`. + * Injects a query: a declarative dependency on an asynchronous source of data + * that is tied to a unique key. + * * @example - * ```angular-ts - * @Component({ + * ```angular-ts + * @Component({ * selector: 'posts', * template: ` - * @if (postsQuery.isPending()) { - * Loading... - * } @else if (postsQuery.isError()) { - * Error: {{ postsQuery.error()?.message }} - * } @else { - *
    - * @for (post of postsQuery.data(); track post.id) { - *
  • {{ post.title }}
  • - * } - *
- * } + * @if (postsQuery.isPending()) { + * Loading... + * } @else if (postsQuery.isError()) { + * Error: {{ postsQuery.error()?.message }} + * } @else { + *
    + * @for (post of postsQuery.data(); track post.id) { + *
  • {{ post.title }}
  • + * } + *
+ * } * `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly postsQuery = injectQuery(() => ({ - * queryKey: ['posts'], - * queryFn: fetchPosts, + * queryKey: ['posts'], + * queryFn: fetchPosts, * })) - * } - * ``` + * } + * ``` + * * @example - * Similar to `computed` from Angular, the function passed to `injectQuery` runs in the reactive context. In - * the example below, the query is automatically enabled and executed when the filter signal changes to a - * truthy value. When the filter signal changes back to a falsy value, the query is disabled. - * ```angular-ts - * @Component({ + * Similar to `computed` from Angular, the function passed to `injectQuery` runs in the reactive context. In + * the example below, the query is automatically enabled and executed when the filter signal changes to a + * truthy value. When the filter signal changes back to a falsy value, the query is disabled. + * ```angular-ts + * @Component({ * selector: 'posts', * template: ` - * - * @if (postsQuery.isPending()) { - * Loading... - * } @else if (postsQuery.isError()) { - * Error: {{ postsQuery.error()?.message }} - * } @else { - *
    - * @for (post of postsQuery.data(); track post.id) { - *
  • {{ post.title }}
  • - * } - *
- * } + * + * @if (postsQuery.isPending()) { + * Loading... + * } @else if (postsQuery.isError()) { + * Error: {{ postsQuery.error()?.message }} + * } @else { + *
    + * @for (post of postsQuery.data(); track post.id) { + *
  • {{ post.title }}
  • + * } + *
+ * } * `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly filter = signal('') * * readonly postsQuery = injectQuery(() => ({ - * queryKey: ['posts', this.filter()], - * queryFn: () => fetchPosts(this.filter()), - * // Signals can be combined with expressions - * enabled: !!this.filter(), + * queryKey: ['posts', this.filter()], + * queryFn: () => fetchPosts(this.filter()), + * // Signals can be combined with expressions + * enabled: !!this.filter(), * })) - * } - * ``` + * } + * ``` + * + * @param injectQueryFn - A function returning the + * {@link UndefinedInitialDataOptions} to use — everything you can pass to + * `injectQuery`. Similar to `computed` from Angular, this function runs in + * the reactive context, so signals read inside it (in `queryKey`, `enabled`, + * etc.) drive the query. + * @param options - Additional configuration + * @returns The query result. `status()` is `'pending'` if there is no cached + * data to display, `'error'` if the last fetch attempt failed, or `'success'` + * if the query has data to display. `isPending`/`isSuccess`/ `isError` are + * type-guard methods for convenience. + * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries + * @see {@link queryOptions} to share these options between `injectQuery` and imperative APIs like + * `queryClient.fetchQuery`. */ export function injectQuery< TQueryFnData = unknown, @@ -169,12 +183,14 @@ export function injectQuery< ): CreateQueryResult /** - * This overload accepts the general {@link CreateQueryOptions} shape rather than the `initialData`-aware - * overloads above, so whether `data` is defined can't be inferred from the call site — useful when wrapping - * `injectQuery` in your own helper function that forwards caller-provided options. - * @param injectQueryFn - A function that returns query options. Similar to `computed` from Angular, this - * function runs in the reactive context, so signals read inside it (in `queryKey`, `enabled`, etc.) drive - * the query. + * This overload accepts the general {@link CreateQueryOptions} shape rather than + * the `initialData`-aware overloads above, so whether `data` is defined can't + * be inferred from the call site — useful when wrapping `injectQuery` in your + * own helper function that forwards caller-provided options. + * + * @param injectQueryFn - A function that returns query options. Similar to + * `computed` from Angular, this function runs in the reactive context, so + * signals read inside it (in `queryKey`, `enabled`, etc.) drive the query. * @param options - Additional configuration * @returns The query result. * @see https://tanstack.com/query/latest/docs/framework/angular/guides/queries diff --git a/packages/angular-query-experimental/src/mutation-options.ts b/packages/angular-query-experimental/src/mutation-options.ts index 399fa035633..b2cf43c3358 100644 --- a/packages/angular-query-experimental/src/mutation-options.ts +++ b/packages/angular-query-experimental/src/mutation-options.ts @@ -2,38 +2,40 @@ import type { DefaultError, WithRequired } from '@tanstack/query-core' import type { CreateMutationOptions } from './types' /** - * You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. A - * `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with - * `injectMutationState`. - * @param options - The mutation options to use, identical to what you'd pass to `injectMutation`, with a - * required `mutationKey`. - * @returns The same options object, unchanged. - * @see {@link injectMutation} to run the mutation these options describe. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `injectMutation`. A `mutationKey` is required on this overload so the + * mutation can be looked up later, e.g. with `injectMutationState`. + * * @example - * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: - * ```angular-ts - * import { mutationOptions, injectMutationState } from '@tanstack/angular-query-experimental' + * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: + * ```angular-ts + * import { mutationOptions, injectMutationState } from '@tanstack/angular-query-experimental' * - * const createPostOptions = mutationOptions({ + * const createPostOptions = mutationOptions({ * mutationKey: ['posts', 'create'], * mutationFn: createPost, - * }) + * }) * - * @Component({ + * @Component({ * selector: 'saving-indicator', * template: ` - * @if (isCreatingPost()) { - * Saving… - * } + * @if (isCreatingPost()) { + * Saving… + * } * `, - * }) - * export class SavingIndicator { + * }) + * export class SavingIndicator { * readonly #pendingCreates = injectMutationState(() => ({ - * filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' }, + * filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' }, * })) * readonly isCreatingPost = computed(() => this.#pendingCreates().length > 0) - * } - * ``` + * } + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `injectMutation`, with a required `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link injectMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, @@ -50,46 +52,51 @@ export function mutationOptions< 'mutationKey' > /** - * You can generally pass everything to `mutationOptions` that you can also pass to `injectMutation`. No - * `mutationKey` is required on this overload — use this when you don't need to target the mutation via a - * `mutationKey` filter later (e.g. with `injectMutationState`); it can still be observed through other + * You can generally pass everything to `mutationOptions` that you can also pass + * to `injectMutation`. No `mutationKey` is required on this overload — use this + * when you don't need to target the mutation via a `mutationKey` filter later + * (e.g. with `injectMutationState`); it can still be observed through other * filters, such as `status`. - * @param options - The mutation options to use, identical to what you'd pass to `injectMutation`, without a - * `mutationKey`. - * @returns The same options object, unchanged. - * @remarks See the other overload's example for looking a mutation up via `injectMutationState`. - * @see {@link injectMutation} to run the mutation these options describe. + * + * @remarks + * See the other overload's example for looking a mutation up via + * `injectMutationState`. * @example - * Sharing options across services, so `QueriesService` stays the single place a mutation is defined: - * ```angular-ts - * import { mutationOptions, injectMutation } from '@tanstack/angular-query-experimental' + * Sharing options across services, so `QueriesService` stays the single place a mutation is defined: + * ```angular-ts + * import { mutationOptions, injectMutation } from '@tanstack/angular-query-experimental' * - * @Injectable({ providedIn: 'root' }) - * export class QueriesService { + * @Injectable({ providedIn: 'root' }) + * export class QueriesService { * readonly #queryClient = inject(QueryClient) * * updatePost(id: number) { - * return mutationOptions({ - * mutationFn: (post: Partial) => putPost(id, post), - * onSuccess: (newPost) => this.#queryClient.setQueryData(['posts', id], newPost), - * }) + * return mutationOptions({ + * mutationFn: (post: Partial) => putPost(id, post), + * onSuccess: (newPost) => this.#queryClient.setQueryData(['posts', id], newPost), + * }) + * } * } - * } * - * @Component({ + * @Component({ * selector: 'post', * template: ``, - * }) - * export class Post { + * }) + * export class Post { * readonly queries = inject(QueriesService) * readonly id = signal(0) * readonly updatePostMutation = injectMutation(() => this.queries.updatePost(this.id())) * * save() { - * this.updatePostMutation.mutate({ title: 'New Title' }) + * this.updatePostMutation.mutate({ title: 'New Title' }) * } - * } - * ``` + * } + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `injectMutation`, without a `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link injectMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, diff --git a/packages/angular-query-experimental/src/pending-tasks-compat.ts b/packages/angular-query-experimental/src/pending-tasks-compat.ts index c4eca3992aa..01a6a334fb7 100644 --- a/packages/angular-query-experimental/src/pending-tasks-compat.ts +++ b/packages/angular-query-experimental/src/pending-tasks-compat.ts @@ -5,8 +5,9 @@ import { noop } from '@tanstack/query-core' type PendingTasksCompat = { add: () => PendingTaskRef } /** - * Removes a pending task registered with Angular's `PendingTasks`, so the app can become stable - * again. Without `PendingTasks` (Angular < 19), it does nothing. + * Removes a pending task registered with Angular's `PendingTasks`, so the app + * can become stable again. Without `PendingTasks` (Angular < 19), it does + * nothing. */ export type PendingTaskRef = () => void diff --git a/packages/angular-query-experimental/src/providers.ts b/packages/angular-query-experimental/src/providers.ts index 827f3153106..f75ce23e52b 100644 --- a/packages/angular-query-experimental/src/providers.ts +++ b/packages/angular-query-experimental/src/providers.ts @@ -3,20 +3,26 @@ import { QueryClient } from '@tanstack/query-core' import type { Provider } from '@angular/core' /** - * Usually {@link provideTanStackQuery} is used once to set up TanStack Query and the - * [`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) for the entire application — - * it calls `provideQueryClient` internally. Use `provideQueryClient` directly to provide a different - * `QueryClient` instance for part of the application, or for unit testing. - * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - * @returns A provider object that can be used to provide the `QueryClient` instance. + * Usually {@link provideTanStackQuery} is used once to set up TanStack Query + * and the + * [`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) + * for the entire application — it calls `provideQueryClient` internally. Use + * `provideQueryClient` directly to provide a different `QueryClient` instance + * for part of the application, or for unit testing. + * * @example - * Providing a test-only `QueryClient` in a component test, without wiring up `provideTanStackQuery`'s other - * defaults: - * ```ts - * TestBed.configureTestingModule({ + * Providing a test-only `QueryClient` in a component test, without wiring up `provideTanStackQuery`'s other + * defaults: + * ```ts + * TestBed.configureTestingModule({ * providers: [provideQueryClient(new QueryClient())], - * }) - * ``` + * }) + * ``` + * + * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which + * provides a `QueryClient`. + * @returns A provider object that can be used to provide the `QueryClient` + * instance. */ export function provideQueryClient( queryClient: QueryClient | InjectionToken, @@ -37,61 +43,72 @@ export function provideQueryClient( } /** - * Sets up providers necessary to enable TanStack Query functionality for Angular applications. Allows - * configuring a `QueryClient` and optional features such as developer tools. - * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which provides a `QueryClient`. - * @param features - Optional features to configure additional Query functionality. - * @returns A set of providers to set up TanStack Query. - * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start - * @see {@link withDevtools} + * Sets up providers necessary to enable TanStack Query functionality for + * Angular applications. Allows configuring a `QueryClient` and optional + * features such as developer tools. + * * @example - * ```ts - * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' + * ```ts + * import { + * provideTanStackQuery, + * QueryClient, + * } from '@tanstack/angular-query-experimental' + * + * bootstrapApplication(AppComponent, { + * providers: [provideTanStackQuery(new QueryClient())], + * }) + * ``` * - * bootstrapApplication(AppComponent, { - * providers: [provideTanStackQuery(new QueryClient())], - * }) - * ``` * @example - * The same, in an `NgModule`-based application: - * ```ts - * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' + * The same, in an `NgModule`-based application: + * ```ts + * import { provideTanStackQuery, QueryClient } from '@tanstack/angular-query-experimental' * - * @NgModule({ + * @NgModule({ * declarations: [AppComponent], * imports: [BrowserModule], * providers: [provideTanStackQuery(new QueryClient())], * bootstrap: [AppComponent], - * }) - * export class AppModule {} - * ``` + * }) + * export class AppModule {} + * ``` + * * @example - * Enabling optional developer tools by adding `withDevtools` — by default, the tools are then loaded when - * your app is in development mode: - * ```ts - * import { + * Enabling optional developer tools by adding `withDevtools` — by default, the tools are then loaded when + * your app is in development mode: + * ```ts + * import { * provideTanStackQuery, * withDevtools, * QueryClient, - * } from '@tanstack/angular-query-experimental' + * } from '@tanstack/angular-query-experimental' * - * bootstrapApplication(AppComponent, { + * bootstrapApplication(AppComponent, { * providers: [provideTanStackQuery(new QueryClient(), withDevtools())], - * }) - * ``` + * }) + * ``` + * * @example - * Using an `InjectionToken` for the `QueryClient` — an advanced optimization that lets TanStack Query be - * absent from the main application bundle, useful for including it on lazy-loaded routes only while still - * sharing a `QueryClient`. This is a small optimization; for most applications it's preferable to provide - * the `QueryClient` in the main application config, as in the examples above: - * ```ts - * export const MY_QUERY_CLIENT = new InjectionToken('', { + * Using an `InjectionToken` for the `QueryClient` — an advanced optimization that lets TanStack Query be + * absent from the main application bundle, useful for including it on lazy-loaded routes only while still + * sharing a `QueryClient`. This is a small optimization; for most applications it's preferable to provide + * the `QueryClient` in the main application config, as in the examples above: + * ```ts + * export const MY_QUERY_CLIENT = new InjectionToken('', { * factory: () => new QueryClient(), - * }) + * }) + * + * // In a lazy loaded route or lazy loaded component's providers array: + * providers: [provideTanStackQuery(MY_QUERY_CLIENT)] + * ``` * - * // In a lazy loaded route or lazy loaded component's providers array: - * providers: [provideTanStackQuery(MY_QUERY_CLIENT)] - * ``` + * @param queryClient - A `QueryClient` instance, or an `InjectionToken` which + * provides a `QueryClient`. + * @param features - Optional features to configure additional Query + * functionality. + * @returns A set of providers to set up TanStack Query. + * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start + * @see {@link withDevtools} */ export function provideTanStackQuery( queryClient: QueryClient | InjectionToken, @@ -104,13 +121,15 @@ export function provideTanStackQuery( } /** - * Sets up providers necessary to enable TanStack Query functionality for Angular applications. + * Sets up providers necessary to enable TanStack Query functionality for + * Angular applications. * * Allows configuring a `QueryClient`. + * + * @deprecated Use `provideTanStackQuery` instead. * @param queryClient - A `QueryClient` instance. * @returns A set of providers to set up TanStack Query. * @see https://tanstack.com/query/v5/docs/framework/angular/quick-start - * @deprecated Use `provideTanStackQuery` instead. */ export function provideAngularQuery(queryClient: QueryClient): Array { return provideTanStackQuery(queryClient) @@ -120,24 +139,20 @@ const queryFeatures = ['Devtools', 'PersistQueryClient'] as const type QueryFeatureKind = (typeof queryFeatures)[number] -/** - * Helper type to represent a Query feature. - */ +/** Helper type to represent a Query feature. */ export interface QueryFeature { - /** - * The kind of the feature, e.g. `'Devtools'` or `'PersistQueryClient'`. - */ + /** The kind of the feature, e.g. `'Devtools'` or `'PersistQueryClient'`. */ ɵkind: TFeatureKind - /** - * The providers that `provideTanStackQuery` registers for the feature. - */ + /** The providers that `provideTanStackQuery` registers for the feature. */ ɵproviders: Array } /** * Helper function to create an object that represents a Query feature. + * * @param kind - The kind of feature, e.g. `'Devtools'`. - * @param providers - The Angular providers this feature contributes to `provideTanStackQuery`. + * @param providers - The Angular providers this feature contributes to + * `provideTanStackQuery`. * @returns A Query feature. */ export function queryFeature( @@ -148,23 +163,26 @@ export function queryFeature( } /** - * A type alias that represents a feature which enables developer tools. - * The type is used to describe the return value of the `withDevtools` function. + * A type alias that represents a feature which enables developer tools. The + * type is used to describe the return value of the `withDevtools` function. + * * @see {@link withDevtools} */ export type DevtoolsFeature = QueryFeature<'Devtools'> /** - * A type alias that represents a feature which enables persistence. - * The type is used to describe the return value of the `withPersistQueryClient` function. + * A type alias that represents a feature which enables persistence. The type is + * used to describe the return value of the `withPersistQueryClient` function. */ export type PersistQueryClientFeature = QueryFeature<'PersistQueryClient'> /** - * A type alias that represents all Query features available for use with `provideTanStackQuery`. - * Features can be enabled by adding special functions to the `provideTanStackQuery` call. - * See documentation for each symbol to find corresponding function name. See also `provideTanStackQuery` - * documentation on how to use those functions. + * A type alias that represents all Query features available for use with + * `provideTanStackQuery`. Features can be enabled by adding special functions + * to the `provideTanStackQuery` call. See documentation for each symbol to find + * corresponding function name. See also `provideTanStackQuery` documentation on + * how to use those functions. + * * @see {@link provideTanStackQuery} */ export type QueryFeatures = DevtoolsFeature | PersistQueryClientFeature diff --git a/packages/angular-query-experimental/src/query-options.ts b/packages/angular-query-experimental/src/query-options.ts index 38d6627943d..ac5c4641884 100644 --- a/packages/angular-query-experimental/src/query-options.ts +++ b/packages/angular-query-experimental/src/query-options.ts @@ -11,8 +11,10 @@ import type { import type { CreateQueryOptions } from './types' /** - * The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be - * `undefined` while the query is `pending`. + * The options accepted by the `queryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -25,11 +27,12 @@ export type UndefinedInitialDataOptions< TQueryKey extends QueryKey = QueryKey, > = CreateQueryOptions & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData?: | undefined @@ -38,8 +41,10 @@ export type UndefinedInitialDataOptions< } /** - * The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is - * not `skipToken` — same as {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`. + * The options accepted by the `queryOptions` overload selected when no + * `initialData` is set and `queryFn` is not `skipToken` — same as + * {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -55,10 +60,12 @@ export type UnusedSkipTokenOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If - * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a - * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been - * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own. + * `skipToken` is not allowed as a value here — this overload is selected when + * no `initialData` is set. If you don't intend to run the query yet, set + * `enabled: false` — omitting `queryFn` alone still triggers a fetch that + * fails with "Missing queryFn" unless `enabled` is `false` or a default query + * function has been defined. A default query function only supplies + * `queryFn`; it doesn't defer the fetch on its own. */ queryFn?: Exclude< CreateQueryOptions['queryFn'], @@ -67,8 +74,10 @@ export type UnusedSkipTokenOptions< } /** - * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never - * `undefined` (unless a `select` changes `TData` to include `undefined`). + * The options accepted by the `queryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -84,64 +93,72 @@ export type DefinedInitialDataOptions< 'queryFn' > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData: | NonUndefinedGuard | (() => NonUndefinedGuard) /** - * Optional here, but omitting it is only safe when no fetch will be attempted — for example with - * `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no - * `queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this. + * Optional here, but omitting it is only safe when no fetch will be attempted + * — for example with `enabled: false`, or when a default query function has + * been defined. Otherwise, an enabled query with no `queryFn` still tries to + * fetch and fails with a "Missing queryFn" error; `initialData` does not + * prevent this. */ queryFn?: QueryFunction } /** - * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is - * required and is the query key to generate options for. + * You can generally pass everything to `queryOptions` that you can also pass to + * `injectQuery`. These options can be shared across functions and imperative + * APIs such as `queryClient.fetchQuery`. `options.queryKey` is required and is + * the query key to generate options for. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `injectQuery`, - * with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link injectQuery} to run a query with these options. - * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. * @example - * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * ```angular-ts + * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' * - * export const postsOptions = queryOptions({ + * export const postsOptions = queryOptions({ * queryKey: ['posts'], * queryFn: fetchPosts, * initialData: [], - * }) + * }) * - * @Component({ + * @Component({ * selector: 'posts', * template: ` - * - * @if (postsQuery.isError()) { - * Error: {{ postsQuery.error()?.message }} - * } - *
    - * @for (post of postsQuery.data(); track post.id) { - *
  • {{ post.title }}
  • - * } - *
+ * + * @if (postsQuery.isError()) { + * Error: {{ postsQuery.error()?.message }} + * } + *
    + * @for (post of postsQuery.data(); track post.id) { + *
  • {{ post.title }}
  • + * } + *
* `, - * }) - * export class Posts { + * }) + * export class Posts { * readonly postsQuery = injectQuery(() => postsOptions) - * } - * ``` + * } + * ``` + * + * @param options - The {@link DefinedInitialDataOptions} to use — everything + * you can pass to `injectQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectQuery} to run a query with these options. + * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. */ export function queryOptions< TQueryFnData = unknown, @@ -154,41 +171,46 @@ export function queryOptions< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is - * required and is the query key to generate options for. - * @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `injectQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link injectQuery} to run a query with these options. - * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + * You can generally pass everything to `queryOptions` that you can also pass to + * `injectQuery`. These options can be shared across functions and imperative + * APIs such as `queryClient.fetchQuery`. `options.queryKey` is required and is + * the query key to generate options for. + * * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * A parameterized factory, so the same options object can be reused per `id`: + * ```angular-ts + * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' * - * export const postOptions = (id: string) => + * export const postOptions = (id: string) => * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), * }) * - * @Component({ + * @Component({ * selector: 'post', * template: ` - * @if (postQuery.isPending()) { - * Loading... - * } @else if (postQuery.isError()) { - * Error: {{ postQuery.error()?.message }} - * } @else { - *

{{ postQuery.data().title }}

- * } + * @if (postQuery.isPending()) { + * Loading... + * } @else if (postQuery.isError()) { + * Error: {{ postQuery.error()?.message }} + * } @else { + *

{{ postQuery.data().title }}

+ * } * `, - * }) - * export class Post { + * }) + * export class Post { * readonly id = signal('1') * readonly postQuery = injectQuery(() => postOptions(this.id())) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UnusedSkipTokenOptions} to use — everything you + * can pass to `injectQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectQuery} to run a query with these options. + * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. */ export function queryOptions< TQueryFnData = unknown, @@ -201,72 +223,79 @@ export function queryOptions< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `injectQuery`. These options - * can be shared across functions and imperative APIs such as `queryClient.fetchQuery`. `options.queryKey` is - * required and is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `injectQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks This is the only overload that accepts `queryFn: skipToken`, shown below. - * @see {@link injectQuery} to run a query with these options. - * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + * You can generally pass everything to `queryOptions` that you can also pass to + * `injectQuery`. These options can be shared across functions and imperative + * APIs such as `queryClient.fetchQuery`. `options.queryKey` is required and is + * the query key to generate options for. + * + * @remarks + * This is the only overload that accepts `queryFn: skipToken`, shown below. * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```angular-ts - * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' + * A parameterized factory, so the same options object can be reused per `id`: + * ```angular-ts + * import { queryOptions, injectQuery } from '@tanstack/angular-query-experimental' * - * export const postOptions = (id: string) => + * export const postOptions = (id: string) => * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), * }) * - * @Component({ + * @Component({ * selector: 'post', * template: ` - * @if (postQuery.isPending()) { - * Loading... - * } @else if (postQuery.isError()) { - * Error: {{ postQuery.error()?.message }} - * } @else { - *

{{ postQuery.data().title }}

- * } + * @if (postQuery.isPending()) { + * Loading... + * } @else if (postQuery.isError()) { + * Error: {{ postQuery.error()?.message }} + * } @else { + *

{{ postQuery.data().title }}

+ * } * `, - * }) - * export class Post { + * }) + * export class Post { * readonly id = signal('1') * readonly postQuery = injectQuery(() => postOptions(this.id())) - * } - * ``` + * } + * ``` + * * @example - * A factory that disables the query, type safe, until `postId` is set: - * ```angular-ts - * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental' + * A factory that disables the query, type safe, until `postId` is set: + * ```angular-ts + * import { queryOptions, skipToken, injectQuery } from '@tanstack/angular-query-experimental' * - * export const postOptions = (postId: number | undefined) => + * export const postOptions = (postId: number | undefined) => * queryOptions({ - * queryKey: ['post', postId], - * queryFn: postId != null ? () => fetchPost(postId) : skipToken, + * queryKey: ['post', postId], + * queryFn: postId != null ? () => fetchPost(postId) : skipToken, * }) * - * @Component({ + * @Component({ * selector: 'post', * template: ` - * @if (postId() == null) { - * Select a post - * } @else if (postQuery.isPending()) { - * Loading... - * } @else if (postQuery.isError()) { - * Error: {{ postQuery.error()?.message }} - * } @else { - *

{{ postQuery.data().title }}

- * } + * @if (postId() == null) { + * Select a post + * } @else if (postQuery.isPending()) { + * Loading... + * } @else if (postQuery.isError()) { + * Error: {{ postQuery.error()?.message }} + * } @else { + *

{{ postQuery.data().title }}

+ * } * `, - * }) - * export class Post { + * }) + * export class Post { * readonly postId = signal(undefined) * readonly postQuery = injectQuery(() => postOptions(this.postId())) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataOptions} to use — everything + * you can pass to `injectQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link injectQuery} to run a query with these options. + * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. */ export function queryOptions< TQueryFnData = unknown, diff --git a/packages/angular-query-experimental/src/signal-proxy.ts b/packages/angular-query-experimental/src/signal-proxy.ts index 8a4d34c128c..7f542948527 100644 --- a/packages/angular-query-experimental/src/signal-proxy.ts +++ b/packages/angular-query-experimental/src/signal-proxy.ts @@ -2,17 +2,20 @@ import { computed, untracked } from '@angular/core' import type { Signal } from '@angular/core' /** - * Maps each field of `T` to a `Signal` of its value. Functions are kept as they are. + * Maps each field of `T` to a `Signal` of its value. Functions are kept as they + * are. */ export type MapToSignals = { [K in keyof T]: T[K] extends Function ? T[K] : Signal } /** - * Exposes fields of an object passed via an Angular `Signal` as `Computed` signals. - * Functions on the object are passed through as-is. + * Exposes fields of an object passed via an Angular `Signal` as `Computed` + * signals. Functions on the object are passed through as-is. + * * @param inputSignal - `Signal` that must return an object. - * @returns A proxy object with the same fields as the input object, but with each field wrapped in a `Computed` signal. + * @returns A proxy object with the same fields as the input object, but with + * each field wrapped in a `Computed` signal. */ export function signalProxy>( inputSignal: Signal, diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index 46dc5f88049..12f5016cd32 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -19,15 +19,18 @@ import type { Signal } from '@angular/core' import type { MapToSignals } from './signal-proxy' /** - * The options shared across `angular-query-experimental`'s query functions. Extends - * {@link QueryObserverOptions} from `@tanstack/query-core` as-is — unlike `react-query`, - * `angular-query-experimental` has no extra framework-specific option here. + * The options shared across `angular-query-experimental`'s query functions. + * Extends {@link QueryObserverOptions} from `@tanstack/query-core` as-is — + * unlike `react-query`, `angular-query-experimental` has no extra + * framework-specific option here. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. - * @template TQueryData - The type of the data actually held in the query cache — the input to `select` and - * `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. + * @template TQueryData - The type of the data actually held in the query cache + * — the input to `select` and `placeholderData`. Defaults to, and is usually + * the same as, `TQueryFnData`. * @template TQueryKey - The type of your `queryKey`. */ export interface CreateBaseQueryOptions< @@ -45,12 +48,14 @@ export interface CreateBaseQueryOptions< > {} /** - * The options accepted by `injectQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` — which - * `angular-query-experimental` doesn't support, unlike `react-query`. + * The options accepted by `injectQuery`. Same as {@link CreateBaseQueryOptions}, + * minus `suspense` — which `angular-query-experimental` doesn't support, unlike + * `react-query`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. * @template TQueryKey - The type of your `queryKey`. */ export interface CreateQueryOptions< @@ -70,16 +75,19 @@ type CreateStatusBasedQueryResult< > = Extract, { status: TStatus }> /** - * The `isSuccess`/`isError`/`isPending` methods on a query result. Unlike `react-query`'s derived booleans, - * these are type-guard methods you call — `if (query.isSuccess())` — so that `query.data` narrows away - * `undefined` inside the branch, the same way `status` narrowing works on the plain object `react-query` - * returns. + * The `isSuccess`/`isError`/`isPending` methods on a query result. Unlike + * `react-query`'s derived booleans, these are type-guard methods you call — `if + * (query.isSuccess())` — so that `query.data` narrows away `undefined` inside + * the branch, the same way `status` narrowing works on the plain object + * `react-query` returns. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ export interface BaseQueryNarrowing { /** - * Returns `true` if the query is in the `success` state, narrowing the result to that state. + * Returns `true` if the query is in the `success` state, narrowing the result + * to that state. */ isSuccess: ( this: CreateBaseQueryResult, @@ -89,7 +97,8 @@ export interface BaseQueryNarrowing { CreateStatusBasedQueryResult<'success', TData, TError> > /** - * Returns `true` if the query is in the `error` state, narrowing the result to that state. + * Returns `true` if the query is in the `error` state, narrowing the result + * to that state. */ isError: ( this: CreateBaseQueryResult, @@ -99,7 +108,8 @@ export interface BaseQueryNarrowing { CreateStatusBasedQueryResult<'error', TData, TError> > /** - * Returns `true` if the query is in the `pending` state, narrowing the result to that state. + * Returns `true` if the query is in the `pending` state, narrowing the result + * to that state. */ isPending: ( this: CreateBaseQueryResult, @@ -111,17 +121,23 @@ export interface BaseQueryNarrowing { } /** - * The options accepted by `injectInfiniteQuery`. Same as {@link CreateBaseQueryOptions}, minus `suspense` — - * which `angular-query-experimental` doesn't support, unlike `react-query` — extends - * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core` for the infinite-query-specific options - * (`getNextPageParam`, `initialPageParam`, etc.). - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by `injectInfiniteQuery`. Same as + * {@link CreateBaseQueryOptions}, minus `suspense` — which + * `angular-query-experimental` doesn't support, unlike `react-query` — extends + * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core` for the + * infinite-query-specific options (`getNextPageParam`, `initialPageParam`, + * etc.). + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` here, though - * `injectInfiniteQuery` itself defaults it to `InfiniteData` — the shape `data` actually has - * when no `select` is used. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` here, though `injectInfiniteQuery` itself defaults it to + * `InfiniteData` — the shape `data` actually has when no + * `select` is used. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export interface CreateInfiniteQueryOptions< TQueryFnData = unknown, @@ -141,12 +157,15 @@ export interface CreateInfiniteQueryOptions< > {} /** - * The result of `injectQuery` when `initialData` isn't set — `data` may be `undefined` while the query is - * `pending`. Same shape as {@link QueryObserverResult} from `@tanstack/query-core`, but value fields (like - * `data`, `error`, `status`) are exposed as a `Signal` — read them with `query.data()`, not `query.data` — - * while function fields (like `refetch`) are called directly, unchanged. `isSuccess`/`isError`/`isPending` - * are {@link BaseQueryNarrowing} type-guard methods rather than plain booleans. + * The result of `injectQuery` when `initialData` isn't set — `data` may be + * `undefined` while the query is `pending`. Same shape as + * {@link QueryObserverResult} from `@tanstack/query-core`, but value fields + * (like `data`, `error`, `status`) are exposed as a `Signal` — read them with + * `query.data()`, not `query.data` — while function fields (like `refetch`) are + * called directly, unchanged. `isSuccess`/`isError`/`isPending` are + * {@link BaseQueryNarrowing} type-guard methods rather than plain booleans. * `injectInfiniteQuery` returns {@link CreateInfiniteQueryResult} instead. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -159,6 +178,7 @@ export type CreateBaseQueryResult< /** * The result of `injectQuery`. Same as {@link CreateBaseQueryResult}. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -168,9 +188,11 @@ export type CreateQueryResult< > = CreateBaseQueryResult /** - * The result of `injectQuery` when `initialData` is set — `data` is never `undefined`. Same shape as - * {@link DefinedQueryObserverResult} from `@tanstack/query-core`, but value fields are exposed as a - * `Signal` while function fields are called directly, unchanged. + * The result of `injectQuery` when `initialData` is set — `data` is never + * `undefined`. Same shape as {@link DefinedQueryObserverResult} from + * `@tanstack/query-core`, but value fields are exposed as a `Signal` while + * function fields are called directly, unchanged. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -182,10 +204,12 @@ export type DefinedCreateQueryResult< MapToSignals> /** - * The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the - * query is `pending`. Same shape as {@link InfiniteQueryObserverResult} from `@tanstack/query-core`, but - * value fields are exposed as a `Signal` while function fields (like `fetchNextPage`) are called directly, - * unchanged. + * The result of `injectInfiniteQuery` when `initialData` isn't set — `data` may + * be `undefined` while the query is `pending`. Same shape as + * {@link InfiniteQueryObserverResult} from `@tanstack/query-core`, but value + * fields are exposed as a `Signal` while function fields (like `fetchNextPage`) + * are called directly, unchanged. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -196,9 +220,11 @@ export type CreateInfiniteQueryResult< MapToSignals> /** - * The result of `injectInfiniteQuery` when `initialData` is set — `data` is never `undefined`. Same shape as - * {@link DefinedInfiniteQueryObserverResult} from `@tanstack/query-core`, but value fields are exposed as a - * `Signal` while function fields are called directly, unchanged. + * The result of `injectInfiniteQuery` when `initialData` is set — `data` is + * never `undefined`. Same shape as {@link DefinedInfiniteQueryObserverResult} + * from `@tanstack/query-core`, but value fields are exposed as a `Signal` while + * function fields are called directly, unchanged. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -212,13 +238,17 @@ export type DefinedCreateInfiniteQueryResult< > = MapToSignals /** - * The options accepted by `injectMutation`. Same as {@link MutationObserverOptions} from - * `@tanstack/query-core`, minus the internal `_defaulted` flag. + * The options accepted by `injectMutation`. Same as + * {@link MutationObserverOptions} from `@tanstack/query-core`, minus the + * internal `_defaulted` flag. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export interface CreateMutationOptions< TData = unknown, @@ -231,15 +261,18 @@ export interface CreateMutationOptions< > {} /** - * The type of `mutate`, as returned by `injectMutation`. Forwards the variables (and an optional per-call - * `onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced - * through the mutation result instead of being thrown by `mutate`, unless `throwOnError` makes - * `injectMutation` rethrow them after emitting them on `ngZone.onError`. + * The type of `mutate`, as returned by `injectMutation`. Forwards the variables + * (and an optional per-call `onSuccess`/`onError`/`onSettled`) to the + * underlying `mutate` call. Fire-and-forget — errors are surfaced through the + * mutation result instead of being thrown by `mutate`, unless `throwOnError` + * makes `injectMutation` rethrow them after emitting them on `ngZone.onError`. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. * @template TVariables - The type of the variable passed to `mutate`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type CreateMutateFunction< TData = unknown, @@ -253,13 +286,15 @@ export type CreateMutateFunction< ) => void /** - * The type of `mutateAsync`, as returned by `injectMutation`. Similar to {@link CreateMutateFunction}, but - * returns a promise which can be awaited. + * The type of `mutateAsync`, as returned by `injectMutation`. Similar to + * {@link CreateMutateFunction}, but returns a promise which can be awaited. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. * @template TVariables - The type of the variable passed to `mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type CreateMutateAsyncFunction< TData = unknown, @@ -269,14 +304,18 @@ export type CreateMutateAsyncFunction< > = MutateFunction /** - * The pre-`Signal` shape {@link CreateMutationResult} is built from — not what `injectMutation` actually - * returns. Same as {@link MutationObserverResult} from `@tanstack/query-core`, with `mutate` narrowed to the - * fire-and-forget {@link CreateMutateFunction} signature, plus the added `mutateAsync`. + * The pre-`Signal` shape {@link CreateMutationResult} is built from — not what + * `injectMutation` actually returns. Same as {@link MutationObserverResult} from + * `@tanstack/query-core`, with `mutate` narrowed to the fire-and-forget + * {@link CreateMutateFunction} signature, plus the added `mutateAsync`. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type CreateBaseMutationResult< TData = unknown, @@ -287,9 +326,7 @@ export type CreateBaseMutationResult< MutationObserverResult, { mutate: CreateMutateFunction } > & { - /** - * Similar to `mutate`, but returns a promise which can be awaited. - */ + /** Similar to `mutate`, but returns a promise which can be awaited. */ mutateAsync: CreateMutateAsyncFunction< TData, TError, @@ -312,14 +349,19 @@ type CreateStatusBasedMutationResult< type SignalFunction any> = T & Signal> /** - * The `isSuccess`/`isError`/`isPending`/`isIdle` methods on a mutation result. Each is both a `Signal` - * (its current boolean value is read reactively without calling it) and a type-guard function you can - * call — `if (mutation.isSuccess())` — so that `mutation.data` narrows away `undefined` inside the branch. + * The `isSuccess`/`isError`/`isPending`/`isIdle` methods on a mutation result. + * Each is both a `Signal` (its current boolean value is read reactively without + * calling it) and a type-guard function you can call — `if + * (mutation.isSuccess())` — so that `mutation.data` narrows away `undefined` + * inside the branch. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export interface BaseMutationNarrowing< TData = unknown, @@ -328,7 +370,8 @@ export interface BaseMutationNarrowing< TOnMutateResult = unknown, > { /** - * Whether the mutation is in the `success` state. Calling it narrows the result to that state. + * Whether the mutation is in the `success` state. Calling it narrows the + * result to that state. */ isSuccess: SignalFunction< ( @@ -348,7 +391,8 @@ export interface BaseMutationNarrowing< > > /** - * Whether the mutation is in the `error` state. Calling it narrows the result to that state. + * Whether the mutation is in the `error` state. Calling it narrows the result + * to that state. */ isError: SignalFunction< ( @@ -368,7 +412,8 @@ export interface BaseMutationNarrowing< > > /** - * Whether the mutation is in the `pending` state. Calling it narrows the result to that state. + * Whether the mutation is in the `pending` state. Calling it narrows the + * result to that state. */ isPending: SignalFunction< ( @@ -388,7 +433,8 @@ export interface BaseMutationNarrowing< > > /** - * Whether the mutation is in the `idle` state. Calling it narrows the result to that state. + * Whether the mutation is in the `idle` state. Calling it narrows the result + * to that state. */ isIdle: SignalFunction< ( @@ -410,15 +456,20 @@ export interface BaseMutationNarrowing< } /** - * The result of `injectMutation`. Based on {@link CreateBaseMutationResult}, but value fields are exposed as - * a `Signal` — read them with `mutation.data()`, not `mutation.data` — while function fields (`mutate`, - * `mutateAsync`, `reset`) are called directly, unchanged. `isSuccess`/`isError`/`isPending`/`isIdle` are - * {@link BaseMutationNarrowing} type-guard methods rather than plain booleans. + * The result of `injectMutation`. Based on {@link CreateBaseMutationResult}, but + * value fields are exposed as a `Signal` — read them with `mutation.data()`, + * not `mutation.data` — while function fields (`mutate`, `mutateAsync`, + * `reset`) are called directly, unchanged. + * `isSuccess`/`isError`/`isPending`/`isIdle` are {@link BaseMutationNarrowing} + * type-guard methods rather than plain booleans. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type CreateMutationResult< TData = unknown, diff --git a/packages/angular-query-persist-client/src/with-persist-query-client.ts b/packages/angular-query-persist-client/src/with-persist-query-client.ts index 43f562450a1..f1343aef31e 100644 --- a/packages/angular-query-persist-client/src/with-persist-query-client.ts +++ b/packages/angular-query-persist-client/src/with-persist-query-client.ts @@ -31,7 +31,7 @@ type PersistQueryClientOptions = { * * ```ts * const localStoragePersister = createAsyncStoragePersister({ - * storage: window.localStorage, + * storage: window.localStorage, * }) * * export const appConfig: ApplicationConfig = { @@ -42,13 +42,17 @@ type PersistQueryClientOptions = { * persistOptions: { * persister: localStoragePersister, * }, - * onSuccess: () => console.log('Restoration completed successfully.'), - * }) + * onSuccess: () => + * console.log('Restoration completed successfully.'), + * }), * ), * ], - * }; + * } * ``` - * @param persistQueryClientOptions - persistence options and optional onSuccess and onError callbacks which get called when the restoration process is complete. + * + * @param persistQueryClientOptions - Persistence options and optional onSuccess + * and onError callbacks which get called when the restoration process is + * complete. * @returns A set of providers for use with `provideTanStackQuery`. * @public */ diff --git a/packages/eslint-plugin-query/src/index.ts b/packages/eslint-plugin-query/src/index.ts index dd2c7413099..8f82bf84f49 100644 --- a/packages/eslint-plugin-query/src/index.ts +++ b/packages/eslint-plugin-query/src/index.ts @@ -5,17 +5,16 @@ import type { RuleModule } from '@typescript-eslint/utils/ts-eslint' type RuleKey = keyof typeof rules /** - * The ESLint plugin object: its `rules`, and its configs — the legacy `recommended` and - * `recommendedStrict`, and the flat `flat/recommended` and `flat/recommended-strict`. + * The ESLint plugin object: its `rules`, and its configs — the legacy + * `recommended` and `recommendedStrict`, and the flat `flat/recommended` and + * `flat/recommended-strict`. */ export interface Plugin extends Omit { - /** - * The rules of the plugin, keyed by rule name. - */ + /** The rules of the plugin, keyed by rule name. */ rules: Record> /** - * The shareable configs: the legacy `recommended` and `recommendedStrict`, and the flat - * `flat/recommended` and `flat/recommended-strict`. + * The shareable configs: the legacy `recommended` and `recommendedStrict`, + * and the flat `flat/recommended` and `flat/recommended-strict`. */ configs: { recommended: ESLint.ConfigData diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts index abd5edebed3..e831c8559ec 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts @@ -171,8 +171,11 @@ export const rule = createRule({ }) /** - * Builds the suggestion that adds the missing dependencies to an array query key. - * @param params - The query key node, the missing paths and their text, and the source code. + * Builds the suggestion that adds the missing dependencies to an array query + * key. + * + * @param params - The query key node, the missing paths and their text, and the + * source code. * @returns The suggestion, or none if the query key is not an array literal. */ function buildSuggestions(params: { @@ -220,11 +223,13 @@ function buildSuggestions(params: { } /** - * Follows variable references and `as` assertions from a query key node to the expression it comes - * from. + * Follows variable references and `as` assertions from a query key node to the + * expression it comes from. + * * @param queryKeyNode - The query key node to start from. * @param context - The rule context, used to resolve variables. - * @returns The innermost node that is neither a resolvable variable nor an `as` assertion. + * @returns The innermost node that is neither a resolvable variable nor an `as` + * assertion. */ function dereferenceVariablesAndTypeAssertions( queryKeyNode: TSESTree.Node, diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts index 2087eb6d471..0e27cca13b3 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts @@ -74,11 +74,14 @@ export const ExhaustiveDepsUtils = { }, /** - * Given required refs and existing queryKey entries, compute missing dependency paths - * respecting allowlisted variables and types. - * @param params - The references the query function needs, the allowlisted variables, and the - * root identifiers and full paths already in the query key. - * @returns The missing dependency paths, without paths whose root is already missing. + * Given required refs and existing queryKey entries, compute missing + * dependency paths respecting allowlisted variables and types. + * + * @param params - The references the query function needs, the allowlisted + * variables, and the root identifiers and full paths already in the query + * key. + * @returns The missing dependency paths, without paths whose root is already + * missing. */ computeFilteredMissingPaths(params: { requiredRefs: Array<{ @@ -122,8 +125,11 @@ export const ExhaustiveDepsUtils = { /** * Extract existing queryKey deps as root identifiers and full member paths. - * @param params - The source code, the scope manager, and the query key node to scan. - * @returns The root identifiers that cover all of their members, and every dependency path. + * + * @param params - The source code, the scope manager, and the query key node + * to scan. + * @returns The root identifiers that cover all of their members, and every + * dependency path. */ collectQueryKeyDeps(params: { sourceCode: Readonly @@ -137,6 +143,7 @@ export const ExhaustiveDepsUtils = { /** * Records an identifier that covers all of its members. + * * @param name - The identifier, normalized before it is recorded. */ function addRoot(name: string) { @@ -146,6 +153,7 @@ export const ExhaustiveDepsUtils = { } /** * Records a full member path. + * * @param text - The path, normalized before it is recorded. */ function addFull(text: string) { @@ -154,6 +162,7 @@ export const ExhaustiveDepsUtils = { } /** * Records a computed reference path as a root or a full path. + * * @param refPath - The reference path, or `null` to record nothing. */ function addRefPath( @@ -175,6 +184,7 @@ export const ExhaustiveDepsUtils = { /** * Visits every child node of a node. + * * @param node - The node whose children are visited. */ function visitChildren(node: TSESTree.Node): void { @@ -201,8 +211,9 @@ export const ExhaustiveDepsUtils = { } /** - * Records the dependencies of a node: identifiers directly, and the external references of - * functions. Other nodes are visited recursively. + * Records the dependencies of a node: identifiers directly, and the + * external references of functions. Other nodes are visited recursively. + * * @param node - The node to visit. */ function visit(node: TSESTree.Node | null | undefined): void { @@ -284,8 +295,10 @@ export const ExhaustiveDepsUtils = { /** * Checks whether the resolved variable is allowlisted by its type annotation. + * * @param params - The allowlisted type names, and the variable to check. - * @returns `true` if a type referenced in the variable's type annotation is allowlisted. + * @returns `true` if a type referenced in the variable's type annotation is + * allowlisted. */ variableIsAllowlistedByType(params: { allowlistedTypes: Set @@ -321,8 +334,10 @@ export const ExhaustiveDepsUtils = { * Normalizes a chain by removing optional chaining operators * * Example: `a?.b.c!` -> `a.b.c` + * * @param text - The source text of the chain. - * @returns The chain without optional chaining, non-null assertions, and whitespace. + * @returns The chain without optional chaining, non-null assertions, and + * whitespace. */ normalizeChain(text: string): string { return text.replace(/(?:\?(\.)|!)/g, '$1').replace(/\s+/g, '') @@ -332,9 +347,11 @@ export const ExhaustiveDepsUtils = { * Computes the reference path for an identifier * * Example: `a.b.c!` -> `{ path: 'a.b.c', root: 'a' }` + * * @param params - The identifier, and the source code to read the chain from. - * @returns The dependency `path`, its `root`, and whether the path is the root itself and covers - * all of its members. For a method call, the method name is dropped from the path. + * @returns The dependency `path`, its `root`, and whether the path is the + * root itself and covers all of its members. For a method call, the method + * name is dropped from the path. */ computeRefPath(params: { identifier: TSESTree.Identifier @@ -390,8 +407,9 @@ export const ExhaustiveDepsUtils = { const externalRefs: Array = [] /** - * Collects the read references of a scope and its child scopes that resolve to variables - * declared outside the function. + * Collects the read references of a scope and its child scopes that resolve + * to variables declared outside the function. + * * @param scope - The scope to collect from. */ function collect(scope: TSESLint.Scope.Scope) { @@ -429,8 +447,9 @@ export const ExhaustiveDepsUtils = { /** * Recursively collects type identifiers from a type annotation. - * @param typeNode - The type to collect from: type references, unions, intersections, arrays, and - * tuples are handled. + * + * @param typeNode - The type to collect from: type references, unions, + * intersections, arrays, and tuples are handled. * @param out - The set the type names are added to. */ collectTypeIdentifiers(typeNode: TSESTree.TypeNode, out: Set): void { @@ -462,8 +481,10 @@ export const ExhaustiveDepsUtils = { }, /** - * Gets the function expression nodes from a queryFn property, handling conditional expressions. - * When neither branch is skipToken, returns both branches so all deps are scanned. + * Gets the function expression nodes from a queryFn property, handling + * conditional expressions. When neither branch is skipToken, returns both + * branches so all deps are scanned. + * * @param queryFn - The `queryFn` property. * @returns The nodes to scan for dependencies. */ diff --git a/packages/eslint-plugin-query/src/rules/infinite-query-property-order/constants.ts b/packages/eslint-plugin-query/src/rules/infinite-query-property-order/constants.ts index 11083028fd5..7fae8877833 100644 --- a/packages/eslint-plugin-query/src/rules/infinite-query-property-order/constants.ts +++ b/packages/eslint-plugin-query/src/rules/infinite-query-property-order/constants.ts @@ -5,7 +5,8 @@ export const infiniteQueryFunctions = [ ] as const /** - * The names of the functions whose options the `infinite-query-property-order` rule checks. + * The names of the functions whose options the `infinite-query-property-order` + * rule checks. */ export type InfiniteQueryFunctions = (typeof infiniteQueryFunctions)[number] @@ -16,7 +17,8 @@ export const checkedProperties = [ ] as const /** - * The option properties whose order the `infinite-query-property-order` rule checks. + * The option properties whose order the `infinite-query-property-order` rule + * checks. */ export type InfiniteQueryProperties = (typeof checkedProperties)[number] diff --git a/packages/eslint-plugin-query/src/rules/mutation-property-order/constants.ts b/packages/eslint-plugin-query/src/rules/mutation-property-order/constants.ts index d7f70fea22f..0b6762a34a7 100644 --- a/packages/eslint-plugin-query/src/rules/mutation-property-order/constants.ts +++ b/packages/eslint-plugin-query/src/rules/mutation-property-order/constants.ts @@ -1,15 +1,14 @@ export const mutationFunctions = ['useMutation'] as const /** - * The names of the functions whose options the `mutation-property-order` rule checks. + * The names of the functions whose options the `mutation-property-order` rule + * checks. */ export type MutationFunctions = (typeof mutationFunctions)[number] export const checkedProperties = ['onMutate', 'onError', 'onSettled'] as const -/** - * The option properties whose order the `mutation-property-order` rule checks. - */ +/** The option properties whose order the `mutation-property-order` rule checks. */ export type MutationProperties = (typeof checkedProperties)[number] export const sortRules = [[['onMutate'], ['onError', 'onSettled']]] as const diff --git a/packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts b/packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts index eb28e935506..fed71bfdb6b 100644 --- a/packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts +++ b/packages/eslint-plugin-query/src/rules/no-rest-destructuring/no-rest-destructuring.utils.ts @@ -23,9 +23,12 @@ const QUERY_RESULT_TYPE_NAMES = new Set([ ]) /** - * Checks whether a type is one of the query result types, or a union that contains one. + * Checks whether a type is one of the query result types, or a union that + * contains one. + * * @param type - The type to check. - * @returns `true` if the type's alias or symbol name is a known query result type. + * @returns `true` if the type's alias or symbol name is a known query result + * type. */ function isQueryResultType(type: Type): boolean { if (type.aliasSymbol && QUERY_RESULT_TYPE_NAMES.has(type.aliasSymbol.name)) { diff --git a/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts b/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts index 699ae594cf3..39103e69ef7 100644 --- a/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts +++ b/packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts @@ -45,8 +45,9 @@ export const rule = createRule({ }> = [] /** - * Returns the name of the React hook a call expression calls, if it is one: a known hook, an - * alias of one, or `React.`. + * Returns the name of the React hook a call expression calls, if it is one: + * a known hook, an alias of one, or `React.`. + * * @param node - The call expression. * @returns The hook name, or `undefined` if the call is not a React hook. */ @@ -71,10 +72,11 @@ export const rule = createRule({ } /** - * Tracks the variables bound to a query hook's result, so they can be reported when used as - * dependencies. - * @param pattern - The binding: an identifier, or an array pattern whose elements and rest - * element are tracked. + * Tracks the variables bound to a query hook's result, so they can be + * reported when used as dependencies. + * + * @param pattern - The binding: an identifier, or an array pattern whose + * elements and rest element are tracked. * @param queryHook - The name of the query hook the result comes from. */ function collectVariableNames( @@ -102,15 +104,19 @@ export const rule = createRule({ /** * Checks whether a name follows the custom hook naming convention. + * * @param hookName - The name to check. - * @returns `true` if the name starts with `use` followed by an uppercase letter or a digit. + * @returns `true` if the name starts with `use` followed by an uppercase + * letter or a digit. */ function isCustomHookName(hookName: string): boolean { return /^use[A-Z0-9]/.test(hookName) } /** - * Checks whether a call passes an object literal with a `combine` property as its first argument. + * Checks whether a call passes an object literal with a `combine` property + * as its first argument. + * * @param callExpression - The call expression to check. * @returns `true` if the first argument has a `combine` property. */ @@ -132,10 +138,13 @@ export const rule = createRule({ } /** - * Returns the name of the TanStack Query hook a call expression calls directly. `useQueries` and - * `useSuspenseQueries` with `combine` are ignored, since their result can be stable. + * Returns the name of the TanStack Query hook a call expression calls + * directly. `useQueries` and `useSuspenseQueries` with `combine` are + * ignored, since their result can be stable. + * * @param callExpression - The call to check. - * @returns The hook name, or `undefined` if the call is not a tracked query hook. + * @returns The hook name, or `undefined` if the call is not a tracked query + * hook. */ function getDirectQueryHook( callExpression: TSESTree.CallExpression, @@ -160,8 +169,9 @@ export const rule = createRule({ } /** - * Returns the query hook behind a call expression: a direct query hook call, or a custom hook that - * returns one. + * Returns the query hook behind a call expression: a direct query hook + * call, or a custom hook that returns one. + * * @param callExpression - The call to check. * @returns The query hook name, or `undefined` if there is none. */ @@ -181,10 +191,13 @@ export const rule = createRule({ } /** - * Returns the query hook that a custom hook's body returns: either an expression body that calls - * one, or a block with a single `return` of such a call. + * Returns the query hook that a custom hook's body returns: either an + * expression body that calls one, or a block with a single `return` of such + * a call. + * * @param body - The body of the custom hook. - * @returns The query hook name, or `undefined` if the body doesn't return one. + * @returns The query hook name, or `undefined` if the body doesn't return + * one. */ function getReturnedQueryHook( body: @@ -216,7 +229,9 @@ export const rule = createRule({ } /** - * Reports the tracked query results used in a React hook's dependency array. + * Reports the tracked query results used in a React hook's dependency + * array. + * * @param reactHook - The name of the React hook. * @param depsArray - The dependency array to check. */ diff --git a/packages/eslint-plugin-query/src/rules/no-void-query-fn/no-void-query-fn.rule.ts b/packages/eslint-plugin-query/src/rules/no-void-query-fn/no-void-query-fn.rule.ts index 132e217ccb1..b580d4e2ead 100644 --- a/packages/eslint-plugin-query/src/rules/no-void-query-fn/no-void-query-fn.rule.ts +++ b/packages/eslint-plugin-query/src/rules/no-void-query-fn/no-void-query-fn.rule.ts @@ -74,11 +74,13 @@ type TypeChecker = ReturnType type Type = ReturnType /** - * Checks whether a query function's return type resolves to `void` or `undefined`, including in any - * member of a union. + * Checks whether a query function's return type resolves to `void` or + * `undefined`, including in any member of a union. + * * @param checker - The TypeScript type checker. * @param type - The return type of the query function. - * @returns `true` if the awaited type, or a member of it, is `void` or `undefined`. + * @returns `true` if the awaited type, or a member of it, is `void` or + * `undefined`. */ function isIllegalReturn(checker: TypeChecker, type: Type): boolean { const awaited = checker.getAwaitedType(type) diff --git a/packages/eslint-plugin-query/src/rules/prefer-query-options/prefer-query-options.rule.ts b/packages/eslint-plugin-query/src/rules/prefer-query-options/prefer-query-options.rule.ts index abd9a5c9aae..3f5c9336826 100644 --- a/packages/eslint-plugin-query/src/rules/prefer-query-options/prefer-query-options.rule.ts +++ b/packages/eslint-plugin-query/src/rules/prefer-query-options/prefer-query-options.rule.ts @@ -76,7 +76,9 @@ export const rule = createRule({ create: detectTanstackQueryImports((context, _, helpers) => { /** - * Reports an object literal passed as query options that defines `queryKey` or `queryFn` inline. + * Reports an object literal passed as query options that defines `queryKey` + * or `queryFn` inline. + * * @param node - The argument passed as query options. */ function reportInlineQueryOptions(node: TSESTree.Node): void { @@ -89,7 +91,9 @@ export const rule = createRule({ } /** - * Reports an object literal passed as query filters whose `queryKey` is an inline array. + * Reports an object literal passed as query filters whose `queryKey` is an + * inline array. + * * @param node - The filters node. */ function reportInlineFilterQueryKey(node: TSESTree.Node): void { @@ -195,6 +199,7 @@ export const rule = createRule({ /** * Checks whether an object literal defines `queryKey` or `queryFn` inline. + * * @param node - The object literal. * @returns `true` if it has a `queryKey` or `queryFn` property. */ @@ -209,8 +214,10 @@ function hasInlineQueryOptions(node: TSESTree.ObjectExpression): boolean { /** * Checks whether an object literal has a `queryKey` written as an inline array. + * * @param node - The object literal. - * @returns `true` if its `queryKey` is an array literal, ignoring type assertions. + * @returns `true` if its `queryKey` is an array literal, ignoring type + * assertions. */ function hasInlineFilterQueryKey(node: TSESTree.ObjectExpression): boolean { const queryKey = ASTUtils.findPropertyWithIdentifierKey( @@ -223,6 +230,7 @@ function hasInlineFilterQueryKey(node: TSESTree.ObjectExpression): boolean { /** * Checks whether a node is an array literal, ignoring type assertions. + * * @param node - The node to check. * @returns `true` if the node is an array literal. */ @@ -231,8 +239,10 @@ function isInlineArrayExpression(node: TSESTree.Node): boolean { } /** - * Collects the object literals a node can evaluate to, following function bodies, `return` - * statements, and conditional, logical, and sequence expressions. + * Collects the object literals a node can evaluate to, following function + * bodies, `return` statements, and conditional, logical, and sequence + * expressions. + * * @param node - The node to collect from. * @returns The object literals the node can evaluate to. */ @@ -287,8 +297,9 @@ function getReturnedObjectExpressions( } /** - * Collects the query option objects of a `queries` array: the object literals in an array literal, - * or those returned by the callback of a `.map()` call. + * Collects the query option objects of a `queries` array: the object literals + * in an array literal, or those returned by the callback of a `.map()` call. + * * @param node - The `queries` value. * @returns The query option object literals. */ @@ -324,12 +335,14 @@ function getQueryObjects( } /** - * Checks whether a node refers to a TanStack Query client, created with `useQueryClient()` or - * `new QueryClient()`. + * Checks whether a node refers to a TanStack Query client, created with + * `useQueryClient()` or `new QueryClient()`. + * * @param node - The node to check. * @param context - The rule context, used to resolve variables. * @param helpers - The helpers that check TanStack Query imports. - * @returns `true` if the node comes from `useQueryClient()` or `new QueryClient()`. + * @returns `true` if the node comes from `useQueryClient()` or `new + * QueryClient()`. */ function isTanstackQueryClient( node: TSESTree.Node, @@ -362,10 +375,12 @@ function isTanstackQueryClient( /** * Returns the name an identifier was imported under from TanStack Query. + * * @param context - The rule context. * @param helpers - The helpers that check TanStack Query imports. * @param node - The identifier. - * @returns The imported name, or `null` if the identifier isn't a named TanStack Query import. + * @returns The imported name, or `null` if the identifier isn't a named + * TanStack Query import. */ function getTanstackImportName( context: Readonly>>, @@ -392,8 +407,9 @@ function getTanstackImportName( } /** - * Follows variable references, optional chains, and type assertions from a node to the expression it - * comes from. + * Follows variable references, optional chains, and type assertions from a node + * to the expression it comes from. + * * @param node - The node to start from. * @param context - The rule context, used to resolve variables. * @returns The innermost node that can't be resolved further. @@ -435,6 +451,7 @@ function resolveQueryClientSource( /** * Removes `as`, `satisfies`, and angle-bracket type assertions around a node. + * * @param node - The node to unwrap. * @returns The node inside the type assertions. */ diff --git a/packages/eslint-plugin-query/src/types.ts b/packages/eslint-plugin-query/src/types.ts index a6dd78e92b4..120bcc1a6b8 100644 --- a/packages/eslint-plugin-query/src/types.ts +++ b/packages/eslint-plugin-query/src/types.ts @@ -1,11 +1,12 @@ /** - * Extra fields in a rule's `meta.docs`: `recommended` is the rule's severity in the recommended - * configs, or `'strict'` if it is only enabled in the strict ones. + * Extra fields in a rule's `meta.docs`: `recommended` is the rule's severity in + * the recommended configs, or `'strict'` if it is only enabled in the strict + * ones. */ export type ExtraRuleDocs = { /** - * The rule's severity in the recommended configs, or `'strict'` if it is only enabled in the - * strict ones. + * The rule's severity in the recommended configs, or `'strict'` if it is only + * enabled in the strict ones. */ recommended: 'strict' | 'error' | 'warn' } diff --git a/packages/eslint-plugin-query/src/utils/create-property-order-rule.ts b/packages/eslint-plugin-query/src/utils/create-property-order-rule.ts index c7117e80c9e..e6390279c84 100644 --- a/packages/eslint-plugin-query/src/utils/create-property-order-rule.ts +++ b/packages/eslint-plugin-query/src/utils/create-property-order-rule.ts @@ -8,12 +8,15 @@ import type { ExtraRuleDocs } from '../types' const createRule = ESLintUtils.RuleCreator(getDocsUrl) /** - * Creates a rule that reports when the properties of the options object passed to the target - * functions are not in the required order. - * @param options - The rule's metadata, such as `name`, `meta`, and `defaultOptions`. - * @param targetFunctions - The names of the functions whose first argument is checked. - * @param orderRules - Pairs of property groups: the properties of the first group must come before - * those of the second. + * Creates a rule that reports when the properties of the options object passed + * to the target functions are not in the required order. + * + * @param options - The rule's metadata, such as `name`, `meta`, and + * `defaultOptions`. + * @param targetFunctions - The names of the functions whose first argument is + * checked. + * @param orderRules - Pairs of property groups: the properties of the first + * group must come before those of the second. * @returns An ESLint rule that reports out-of-order properties and fixes them. */ export function createPropertyOrderRule< @@ -29,6 +32,7 @@ export function createPropertyOrderRule< const targetFunctionSet = new Set(targetFunctions) /** * Checks whether a function name is one of the target functions. + * * @param node - The function name. * @returns `true` if the name is a target function. */ diff --git a/packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts b/packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts index abf9d2b6817..3611c580aa8 100644 --- a/packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts +++ b/packages/eslint-plugin-query/src/utils/detect-react-query-imports.ts @@ -22,9 +22,11 @@ type EnhancedCreate = ( ) => ReturnType /** - * Wraps a rule's `create` function to track the identifiers imported from TanStack Query packages, - * and passes helpers that check them. - * @param create - The rule's `create` function, which also receives the helpers. + * Wraps a rule's `create` function to track the identifiers imported from + * TanStack Query packages, and passes helpers that check them. + * + * @param create - The rule's `create` function, which also receives the + * helpers. * @returns The wrapped `create` function. */ export function detectTanstackQueryImports(create: EnhancedCreate): Create { diff --git a/packages/eslint-plugin-query/src/utils/get-docs-url.ts b/packages/eslint-plugin-query/src/utils/get-docs-url.ts index 2a43bf7fd38..cb1f54b3f9f 100644 --- a/packages/eslint-plugin-query/src/utils/get-docs-url.ts +++ b/packages/eslint-plugin-query/src/utils/get-docs-url.ts @@ -1,5 +1,6 @@ /** * Builds the URL of a rule's documentation page. + * * @param ruleName - The rule's name, e.g. `exhaustive-deps`. * @returns The URL of the rule's page in the ESLint plugin docs. */ diff --git a/packages/eslint-plugin-query/src/utils/sort-data-by-order.ts b/packages/eslint-plugin-query/src/utils/sort-data-by-order.ts index f0db24fb2a1..87ea2a18d95 100644 --- a/packages/eslint-plugin-query/src/utils/sort-data-by-order.ts +++ b/packages/eslint-plugin-query/src/utils/sort-data-by-order.ts @@ -1,9 +1,10 @@ /** - * Sorts the items covered by the order rules into the required order, keeping the other items in - * place. + * Sorts the items covered by the order rules into the required order, keeping + * the other items in place. + * * @param data - The items to sort. - * @param orderRules - Pairs of groups: items whose `key` is in the first group must come before - * those in the second. + * @param orderRules - Pairs of groups: items whose `key` is in the first group + * must come before those in the second. * @param key - The property of each item to compare against the groups. * @returns The sorted items, or `null` if they were already in order. */ diff --git a/packages/eslint-plugin-query/src/utils/unique-by.ts b/packages/eslint-plugin-query/src/utils/unique-by.ts index dfc374fecb2..1f84f2cb999 100644 --- a/packages/eslint-plugin-query/src/utils/unique-by.ts +++ b/packages/eslint-plugin-query/src/utils/unique-by.ts @@ -1,5 +1,6 @@ /** * Removes duplicate items, keeping the first item for each key. + * * @param arr - The items. * @param fn - Returns the key that identifies an item. * @returns The items with unique keys, in their original order. diff --git a/packages/lit-query/src/QueryClientProvider.ts b/packages/lit-query/src/QueryClientProvider.ts index 65cd31be6ae..a13a41b217d 100644 --- a/packages/lit-query/src/QueryClientProvider.ts +++ b/packages/lit-query/src/QueryClientProvider.ts @@ -10,54 +10,58 @@ import type { QueryClient } from '@tanstack/query-core' import type { TemplateResult } from 'lit' /** - * Lit element that provides a `QueryClient` to descendant Lit Query - * controllers through Lit context. + * Lit element that provides a `QueryClient` to descendant Lit Query controllers + * through Lit context. * * The `client` is a property, not an attribute. When rendering this element in - * a Lit template, bind it with property binding: `.client=${queryClient}`. - * The provider throws if it connects without a client, or if an already - * connected provider has its client cleared. + * a Lit template, bind it with property binding: `.client=${queryClient}`. The + * provider throws if it connects without a client, or if an already connected + * provider has its client cleared. * * This class is not registered as a custom element by the package. Applications * must register either a subclass or the class itself with * `customElements.define`. + * * @example - * ```ts - * import { html, LitElement } from 'lit' - * import { QueryClient, QueryClientProvider } from '@tanstack/lit-query' + * ```ts + * import { html, LitElement } from 'lit' + * import { QueryClient, QueryClientProvider } from '@tanstack/lit-query' * - * const queryClient = new QueryClient() + * const queryClient = new QueryClient() * - * class AppQueryProvider extends QueryClientProvider { - * constructor() { - * super() - * this.client = queryClient + * class AppQueryProvider extends QueryClientProvider { + * constructor() { + * super() + * this.client = queryClient + * } * } - * } * - * customElements.define('app-query-provider', AppQueryProvider) + * customElements.define('app-query-provider', AppQueryProvider) * - * class AppRoot extends LitElement { - * render() { - * return html`` + * class AppRoot extends LitElement { + * render() { + * return html`` + * } * } - * } - * ``` + * ``` + * * @example - * ```ts - * import { html } from 'lit' - * import { QueryClient, QueryClientProvider } from '@tanstack/lit-query' + * ```ts + * import { html } from 'lit' + * import { QueryClient, QueryClientProvider } from '@tanstack/lit-query' * - * const queryClient = new QueryClient() + * const queryClient = new QueryClient() * - * customElements.define('query-client-provider', QueryClientProvider) + * customElements.define('query-client-provider', QueryClientProvider) * - * const view = html` + * const view = html` * * * * ` - * ``` + * ``` */ export class QueryClientProvider extends LitElement { /** @internal */ @@ -87,6 +91,7 @@ export class QueryClientProvider extends LitElement { /** * Provides the client to descendants and mounts it when the element is * connected. + * * @internal */ override connectedCallback(): void { @@ -98,6 +103,7 @@ export class QueryClientProvider extends LitElement { /** * Unmounts the client when the element is disconnected. + * * @internal */ override disconnectedCallback(): void { @@ -107,10 +113,12 @@ export class QueryClientProvider extends LitElement { /** * Swaps the provided and mounted client when `client` changes. - * @internal - * @param changedProperties - The properties that changed. When `client` changes, the previous - * client is unmounted and the new one is provided and mounted. + * + * @param changedProperties - The properties that changed. When `client` + * changes, the previous client is unmounted and the new one is provided and + * mounted. * @throws {Error} If `client` is unset while the provider is connected. + * @internal */ protected override willUpdate( changedProperties: Map, @@ -148,8 +156,9 @@ export class QueryClientProvider extends LitElement { /** * Renders the provider's children. - * @internal + * * @returns A `` that renders the provider's children. + * @internal */ override render(): TemplateResult { return html`` diff --git a/packages/lit-query/src/accessor.ts b/packages/lit-query/src/accessor.ts index ee9e6f6c155..fbb4d1bb200 100644 --- a/packages/lit-query/src/accessor.ts +++ b/packages/lit-query/src/accessor.ts @@ -3,16 +3,22 @@ * * Lit Query APIs read function accessors during host updates, so the getter can * depend on reactive host state. + * * @example - * ```ts - * const staticKey: Accessor = ['todos'] - * const reactiveKey: Accessor = () => ['todos', this.userId] - * ``` + * ```ts + * const staticKey: Accessor = ['todos'] + * const reactiveKey: Accessor = () => [ + * 'todos', + * this.userId, + * ] + * ``` */ export type Accessor = T | (() => T) /** - * Reads an {@link Accessor}: calls it if it is a function, otherwise returns it as is. + * Reads an {@link Accessor}: calls it if it is a function, otherwise returns it + * as is. + * * @param value - The value, or a getter that returns it. * @returns The value. */ @@ -26,21 +32,24 @@ export function readAccessor(value: Accessor): T { * * Controller creators and cache state helpers return this shape so render code * can use either `result()` or `result.current`. + * * @example - * ```ts - * const query = this.todos() - * const sameQuery = this.todos.current - * ``` + * ```ts + * const query = this.todos() + * const sameQuery = this.todos.current + * ``` */ export type ValueAccessor = (() => T) & { readonly current: T } /** - * Creates a {@link ValueAccessor} that reads its value from `getter`, both when called and through - * its `current` property. + * Creates a {@link ValueAccessor} that reads its value from `getter`, both when + * called and through its `current` property. + * * @param getter - Returns the latest value. - * @returns A function that returns the latest value, which is also available on `current`. + * @returns A function that returns the latest value, which is also available on + * `current`. */ export function createValueAccessor(getter: () => T): ValueAccessor { const accessor = (() => getter()) as ValueAccessor diff --git a/packages/lit-query/src/context.ts b/packages/lit-query/src/context.ts index 3e3648bbcee..6c54a714056 100644 --- a/packages/lit-query/src/context.ts +++ b/packages/lit-query/src/context.ts @@ -26,6 +26,7 @@ let defaultClient: QueryClient | undefined * * `QueryClientProvider` calls this automatically while it is connected. Prefer * passing an explicit client or rendering under a provider when possible. + * * @param client - The query client to register as the current default. */ export function registerDefaultQueryClient(client: QueryClient): void { @@ -34,10 +35,10 @@ export function registerDefaultQueryClient(client: QueryClient): void { } /** - * Unregisters a client previously registered with - * `registerDefaultQueryClient`. + * Unregisters a client previously registered with `registerDefaultQueryClient`. * * `QueryClientProvider` calls this automatically when it disconnects. + * * @param client - The query client registration to release. */ export function unregisterDefaultQueryClient(client: QueryClient): void { @@ -61,10 +62,11 @@ export function unregisterDefaultQueryClient(client: QueryClient): void { } /** - * Returns the registered default `QueryClient`, if exactly one default client is - * available. + * Returns the registered default `QueryClient`, if exactly one default client + * is available. + * * @returns The default query client, or `undefined` when there is no registered - * client or more than one registered client. + * client or more than one registered client. */ export function getDefaultQueryClient(): QueryClient | undefined { if (registeredClients.size > 1) { @@ -76,6 +78,7 @@ export function getDefaultQueryClient(): QueryClient | undefined { /** * Creates the error thrown when no `QueryClient` is available. + * * @returns A new `Error` explaining that no `QueryClient` is available. */ export function createMissingQueryClientError(): Error { @@ -83,9 +86,11 @@ export function createMissingQueryClientError(): Error { } /** - * Creates the error thrown when multiple `QueryClient`s are mounted and the default one would be - * ambiguous. - * @returns A new `Error` explaining that the default `QueryClient` is ambiguous. + * Creates the error thrown when multiple `QueryClient`s are mounted and the + * default one would be ambiguous. + * + * @returns A new `Error` explaining that the default `QueryClient` is + * ambiguous. */ function createAmbiguousQueryClientError(): Error { return new Error(ambiguousQueryClientMessage) @@ -98,9 +103,10 @@ function createAmbiguousQueryClientError(): Error { * This helper is useful outside a Lit reactive controller when a single * provider is mounted. It throws if no client is registered or if multiple * clients are mounted and the default would be ambiguous. + * * @returns The single registered query client. - * @throws {Error} If no `QueryClient` is registered, or if multiple are - * mounted and the default is ambiguous. + * @throws {Error} If no `QueryClient` is registered, or if multiple are mounted + * and the default is ambiguous. */ export function useQueryClient(): QueryClient { const client = getDefaultQueryClient() @@ -117,9 +123,10 @@ export function useQueryClient(): QueryClient { /** * Resolves an explicit `QueryClient` or falls back to `useQueryClient`. + * * @param explicit - Optional client supplied by the caller. * @returns The explicit client when provided, otherwise the current default - * client. + * client. */ export function resolveQueryClient(explicit?: QueryClient): QueryClient { return explicit ?? useQueryClient() diff --git a/packages/lit-query/src/controllers/BaseController.ts b/packages/lit-query/src/controllers/BaseController.ts index aec0fbee617..345c72a4541 100644 --- a/packages/lit-query/src/controllers/BaseController.ts +++ b/packages/lit-query/src/controllers/BaseController.ts @@ -121,9 +121,9 @@ export abstract class BaseController implements ReactiveController { } /** - * Permanently disconnects the controller and removes it from its host, if - * the host supports `removeController`. The controller ignores later - * lifecycle callbacks. + * Permanently disconnects the controller and removes it from its host, if the + * host supports `removeController`. The controller ignores later lifecycle + * callbacks. */ destroy(): void { if (this.destroyed) { @@ -146,8 +146,9 @@ export abstract class BaseController implements ReactiveController { /** * Returns the `QueryClient` without throwing when none is available. + * * @returns The explicitly passed client, otherwise the client from context, - * or `undefined` if neither is available. + * or `undefined` if neither is available. */ protected tryGetQueryClient(): QueryClient | undefined { return this.explicitClient ?? this.contextClient @@ -155,6 +156,7 @@ export abstract class BaseController implements ReactiveController { /** * Returns the `QueryClient`, throwing when none is available. + * * @returns The explicitly passed client, otherwise the client from context. * @throws {Error} If no `QueryClient` is available. */ @@ -170,6 +172,7 @@ export abstract class BaseController implements ReactiveController { /** * Stores a new result and requests a host update, unless it is the same * result or the host is already updating. + * * @param next - The new result. */ protected setResult(next: TResult): void { @@ -185,6 +188,7 @@ export abstract class BaseController implements ReactiveController { /** * The latest result of the controller. + * * @returns The latest result. * @throws {Error} If no `QueryClient` could be resolved from context. */ @@ -198,15 +202,14 @@ export abstract class BaseController implements ReactiveController { /** * Whether the controller's host is connected. + * * @returns `true` while the host is connected. */ protected get connectedState(): boolean { return this.connected } - /** - * Requests a host update in a microtask, batching multiple calls into one. - */ + /** Requests a host update in a microtask, batching multiple calls into one. */ protected queueUpdate(): void { if (this.updateQueued) { return @@ -338,19 +341,17 @@ export abstract class BaseController implements ReactiveController { } /** - * Called in a microtask after the host connects, once the subclass fields - * are initialized. Subclasses subscribe to the `QueryClient` here, if one is + * Called in a microtask after the host connects, once the subclass fields are + * initialized. Subclasses subscribe to the `QueryClient` here, if one is * available. */ protected abstract onConnected(): void /** - * Called when the host disconnects or the controller is destroyed. - * Subclasses unsubscribe here. + * Called when the host disconnects or the controller is destroyed. Subclasses + * unsubscribe here. */ protected abstract onDisconnected(): void - /** - * Called before each host update. Subclasses refresh their options here. - */ + /** Called before each host update. Subclasses refresh their options here. */ protected abstract onHostUpdate(): void /** * Called in a microtask when the `QueryClient` from context changes, or when diff --git a/packages/lit-query/src/createInfiniteQueryController.ts b/packages/lit-query/src/createInfiniteQueryController.ts index 393fcb9c240..28f994b33b2 100644 --- a/packages/lit-query/src/createInfiniteQueryController.ts +++ b/packages/lit-query/src/createInfiniteQueryController.ts @@ -59,8 +59,9 @@ export type InfiniteQueryResultAccessor = ValueAccessor< } /** - * Returns the result used while no `QueryClient` is available: `'pending'` and idle, with methods - * that reject with the missing client error. + * Returns the result used while no `QueryClient` is available: `'pending'` and + * idle, with methods that reject with the missing client error. + * * @returns A new result object in that state. */ function createPendingInfiniteQueryResult< @@ -365,38 +366,43 @@ class InfiniteQueryController< * * If `queryClient` is omitted, the controller resolves the client from the * nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the infinite query - * subscription. - * @param options - Infinite query observer options, or a getter that returns - * options. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the latest infinite query result with page helper - * methods. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { createInfiniteQueryController } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { createInfiniteQueryController } from '@tanstack/lit-query' * - * class ProjectsView extends LitElement { - * private readonly projects = createInfiniteQueryController(this, { - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextCursor, - * }) + * class ProjectsView extends LitElement { + * private readonly projects = createInfiniteQueryController(this, { + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextCursor, + * }) * - * render() { - * const query = this.projects() + * render() { + * const query = this.projects() * - * return html` - * * ` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the infinite query + * subscription. + * @param options - Infinite query observer options, or a getter that returns + * options. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the latest infinite query result with page helper + * methods. */ export function createInfiniteQueryController< TQueryFnData = unknown, diff --git a/packages/lit-query/src/createMutationController.ts b/packages/lit-query/src/createMutationController.ts index bfe8f45a5c5..88162dd4aaa 100644 --- a/packages/lit-query/src/createMutationController.ts +++ b/packages/lit-query/src/createMutationController.ts @@ -68,8 +68,9 @@ export type MutationResultAccessor = } /** - * Returns the result used while no `QueryClient` is available: `'idle'`, with a `mutate` that - * rejects with the missing client error. + * Returns the result used while no `QueryClient` is available: `'idle'`, with a + * `mutate` that rejects with the missing client error. + * * @returns A new result object in that state. */ function createIdleMutationResult< @@ -293,35 +294,43 @@ class MutationController< * * If `queryClient` is omitted, the controller resolves the client from the * nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the mutation - * subscription. - * @param options - Mutation observer options, or a getter that returns options. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the latest mutation result with mutation helper - * methods. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { createMutationController } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { createMutationController } from '@tanstack/lit-query' * - * class AddTodoForm extends LitElement { - * private readonly addTodo = createMutationController(this, { - * mutationFn: (title: string) => - * fetch('/api/todos', { method: 'POST', body: JSON.stringify({ title }) }), - * }) + * class AddTodoForm extends LitElement { + * private readonly addTodo = createMutationController(this, { + * mutationFn: (title: string) => + * fetch('/api/todos', { + * method: 'POST', + * body: JSON.stringify({ title }), + * }), + * }) * - * render() { - * const mutation = this.addTodo() + * render() { + * const mutation = this.addTodo() * - * return html` - * * ` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the mutation + * subscription. + * @param options - Mutation observer options, or a getter that returns options. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the latest mutation result with mutation helper + * methods. */ export function createMutationController< TData = unknown, diff --git a/packages/lit-query/src/createQueriesController.ts b/packages/lit-query/src/createQueriesController.ts index 04af594e605..4ce71e330cd 100644 --- a/packages/lit-query/src/createQueriesController.ts +++ b/packages/lit-query/src/createQueriesController.ts @@ -217,8 +217,9 @@ export type QueriesResultAccessor = } /** - * Returns the result used while no `QueryClient` is available: `'pending'` and idle, with methods - * that reject with the missing client error. + * Returns the result used while no `QueryClient` is available: `'pending'` and + * idle, with methods that reject with the missing client error. + * * @returns A new result object in that state. */ function createPendingQueryObserverResult(): QueryObserverResult { @@ -255,8 +256,10 @@ function createPendingQueryObserverResult(): QueryObserverResult { } /** - * Returns the result of a query used while no `QueryClient` is available: a `'success'` result with - * the query's `initialData` (after `select`), or the pending result if there is no `initialData`. + * Returns the result of a query used while no `QueryClient` is available: a + * `'success'` result with the query's `initialData` (after `select`), or the + * pending result if there is no `initialData`. + * * @param query - The query options. * @returns The `'success'` result with `initialData`, or a pending one. */ @@ -292,6 +295,7 @@ function createPlaceholderQueryObserverResult( /** * Reads the controller's options and defaults each query with the client. + * * @param optionsAccessor - The options, or a getter that returns them. * @param client - The client used to default the query options. * @returns The defaulted query options and the `combine` function. @@ -676,37 +680,40 @@ class QueriesController< * * If `queryClient` is omitted, the controller resolves the client from the * nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the queries - * subscription. - * @param options - Queries controller options, or a getter that returns options. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the latest query results, or the value returned by - * `combine`. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { createQueriesController } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { createQueriesController } from '@tanstack/lit-query' * - * class DashboardView extends LitElement { - * private readonly dashboard = createQueriesController(this, { - * queries: [ - * { queryKey: ['stats'], queryFn: fetchStats }, - * { queryKey: ['projects'], queryFn: fetchProjects }, - * ], - * combine: ([stats, projects]) => ({ - * stats: stats.data, - * projects: projects.data ?? [], - * isPending: stats.isPending || projects.isPending, - * }), - * }) + * class DashboardView extends LitElement { + * private readonly dashboard = createQueriesController(this, { + * queries: [ + * { queryKey: ['stats'], queryFn: fetchStats }, + * { queryKey: ['projects'], queryFn: fetchProjects }, + * ], + * combine: ([stats, projects]) => ({ + * stats: stats.data, + * projects: projects.data ?? [], + * isPending: stats.isPending || projects.isPending, + * }), + * }) * - * render() { - * const dashboard = this.dashboard() - * return html`

Projects: ${dashboard.projects.length}

` + * render() { + * const dashboard = this.dashboard() + * return html`

Projects: ${dashboard.projects.length}

` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the queries + * subscription. + * @param options - Queries controller options, or a getter that returns + * options. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the latest query results, or the value returned by + * `combine`. */ export function createQueriesController< TQueryOptions extends Array, diff --git a/packages/lit-query/src/createQueryController.ts b/packages/lit-query/src/createQueryController.ts index b4697607cf5..eefd6a6fe04 100644 --- a/packages/lit-query/src/createQueryController.ts +++ b/packages/lit-query/src/createQueryController.ts @@ -47,8 +47,9 @@ export type QueryResultAccessor = ValueAccessor< } /** - * Returns the result used while no `QueryClient` is available: `'pending'` and idle, with methods - * that reject with the missing client error. + * Returns the result used while no `QueryClient` is available: `'pending'` and + * idle, with methods that reject with the missing client error. + * * @returns A new result object in that state. */ function createPendingQueryResult(): QueryObserverResult< @@ -317,33 +318,37 @@ class QueryController< * * If `queryClient` is omitted, the controller resolves the client from the * nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the query - * subscription. - * @param options - Query observer options, or a getter that returns options. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the latest query result with query helper methods. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { createQueryController } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { createQueryController } from '@tanstack/lit-query' * - * class TodosView extends LitElement { - * private readonly todos = createQueryController(this, { - * queryKey: ['todos'], - * queryFn: async () => fetch('/api/todos').then((r) => r.json()), - * }) + * class TodosView extends LitElement { + * private readonly todos = createQueryController(this, { + * queryKey: ['todos'], + * queryFn: async () => fetch('/api/todos').then((r) => r.json()), + * }) * - * render() { - * const query = this.todos() + * render() { + * const query = this.todos() * - * if (query.isPending) return html`Loading...` - * if (query.isError) return html`Error` + * if (query.isPending) return html`Loading...` + * if (query.isError) return html`Error` * - * return html`
    ${query.data.map((todo) => html`
  • ${todo.title}
  • `)}
` + * return html`
    + * ${query.data.map((todo) => html`
  • ${todo.title}
  • `)} + *
` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the query + * subscription. + * @param options - Query observer options, or a getter that returns options. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the latest query result with query helper methods. */ export function createQueryController< TQueryFnData = unknown, diff --git a/packages/lit-query/src/infiniteQueryOptions.ts b/packages/lit-query/src/infiniteQueryOptions.ts index 6778f80c9c4..7031ae8ca65 100644 --- a/packages/lit-query/src/infiniteQueryOptions.ts +++ b/packages/lit-query/src/infiniteQueryOptions.ts @@ -9,19 +9,21 @@ import type { /** * Brands infinite query options so the `queryKey` carries the infinite query * data and error types across TanStack Query APIs. - * @param options - Infinite query options to preserve and brand. - * @returns The same options object with a typed `queryKey`. + * * @example - * ```ts - * import { infiniteQueryOptions } from '@tanstack/lit-query' + * ```ts + * import { infiniteQueryOptions } from '@tanstack/lit-query' * - * const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextCursor, - * }) - * ``` + * const projectsOptions = infiniteQueryOptions({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextCursor, + * }) + * ``` + * + * @param options - Infinite query options to preserve and brand. + * @returns The same options object with a typed `queryKey`. */ export function infiniteQueryOptions< TQueryFnData = unknown, diff --git a/packages/lit-query/src/mutationOptions.ts b/packages/lit-query/src/mutationOptions.ts index 4b7ec12ddd0..0e0329f76a2 100644 --- a/packages/lit-query/src/mutationOptions.ts +++ b/packages/lit-query/src/mutationOptions.ts @@ -5,17 +5,19 @@ import type { /** * Preserves and types mutation options for reuse across Lit Query APIs. - * @param options - Mutation options to preserve. - * @returns The same options object. + * * @example - * ```ts - * import { mutationOptions } from '@tanstack/lit-query' + * ```ts + * import { mutationOptions } from '@tanstack/lit-query' * - * const addTodoOptions = mutationOptions({ - * mutationKey: ['add-todo'], - * mutationFn: (title: string) => addTodo(title), - * }) - * ``` + * const addTodoOptions = mutationOptions({ + * mutationKey: ['add-todo'], + * mutationFn: (title: string) => addTodo(title), + * }) + * ``` + * + * @param options - Mutation options to preserve. + * @returns The same options object. */ export function mutationOptions< TData = unknown, diff --git a/packages/lit-query/src/queryObserverResultTracker.ts b/packages/lit-query/src/queryObserverResultTracker.ts index 12bb54e283d..7477752f9c9 100644 --- a/packages/lit-query/src/queryObserverResultTracker.ts +++ b/packages/lit-query/src/queryObserverResultTracker.ts @@ -11,9 +11,7 @@ export class QueryObserverResultTracker { private result: TResult | undefined private usesTracking = false - /** - * Forgets the last result, so the next `update` returns a result again. - */ + /** Forgets the last result, so the next `update` returns a result again. */ reset(): void { this.result = undefined this.usesTracking = false @@ -22,10 +20,11 @@ export class QueryObserverResultTracker { /** * Returns the result to expose, tracked through the observer when it uses * property tracking. + * * @param observer - The observer the result comes from, if any. * @param result - The latest result of the observer. - * @returns The result to expose, or `undefined` if neither the result nor - * the tracking mode changed since the last call. + * @returns The result to expose, or `undefined` if neither the result nor the + * tracking mode changed since the last call. */ update( observer: TrackableQueryObserver | undefined, diff --git a/packages/lit-query/src/queryOptions.ts b/packages/lit-query/src/queryOptions.ts index d1cca2c03d3..80daa6e62ad 100644 --- a/packages/lit-query/src/queryOptions.ts +++ b/packages/lit-query/src/queryOptions.ts @@ -10,9 +10,7 @@ import type { SkipToken, } from '@tanstack/query-core' -/** - * Query options with `initialData` that guarantees defined query data. - */ +/** Query options with `initialData` that guarantees defined query data. */ export type DefinedInitialDataOptions< TQueryFnData = unknown, TError = DefaultError, @@ -28,9 +26,7 @@ export type DefinedInitialDataOptions< queryFn?: QueryFunction } -/** - * Query options where `queryFn` is present and not a `skipToken`. - */ +/** Query options where `queryFn` is present and not a `skipToken`. */ export type UnusedSkipTokenOptions< TQueryFnData = unknown, TError = DefaultError, @@ -52,9 +48,7 @@ export type UnusedSkipTokenOptions< > } -/** - * Query options where `initialData` can be omitted or undefined. - */ +/** Query options where `initialData` can be omitted or undefined. */ export type UndefinedInitialDataOptions< TQueryFnData = unknown, TError = DefaultError, @@ -76,18 +70,20 @@ export type UndefinedInitialDataOptions< /** * Brands query options so the `queryKey` carries the query function data and * error types across TanStack Query APIs. - * @param options - Query options to preserve and brand. - * @returns The same options object with a typed `queryKey`. + * * @example - * ```ts - * import { queryOptions } from '@tanstack/lit-query' + * ```ts + * import { queryOptions } from '@tanstack/lit-query' * - * const todosOptions = queryOptions({ - * queryKey: ['todos'], - * queryFn: fetchTodos, - * initialData: [], - * }) - * ``` + * const todosOptions = queryOptions({ + * queryKey: ['todos'], + * queryFn: fetchTodos, + * initialData: [], + * }) + * ``` + * + * @param options - Query options to preserve and brand. + * @returns The same options object with a typed `queryKey`. */ export function queryOptions< TQueryFnData = unknown, @@ -103,6 +99,7 @@ export function queryOptions< /** * Brands query options so the `queryKey` carries the query function data and * error types across TanStack Query APIs. + * * @param options - Query options to preserve and brand. * @returns The same options object with a typed `queryKey`. */ @@ -120,6 +117,7 @@ export function queryOptions< /** * Brands query options so the `queryKey` carries the query function data and * error types across TanStack Query APIs. + * * @param options - Query options to preserve and brand. * @returns The same options object with a typed `queryKey`. */ diff --git a/packages/lit-query/src/types.ts b/packages/lit-query/src/types.ts index 4eca18ed4e1..63145a18c3e 100644 --- a/packages/lit-query/src/types.ts +++ b/packages/lit-query/src/types.ts @@ -14,9 +14,7 @@ import type { } from './createQueriesController.js' import type { CreateQueryOptions } from './createQueryController.js' -/** - * Accessor-wrapped options accepted by `createQueryController`. - */ +/** Accessor-wrapped options accepted by `createQueryController`. */ export type QueryControllerOptions< TQueryFnData = unknown, TError = DefaultError, @@ -27,17 +25,13 @@ export type QueryControllerOptions< CreateQueryOptions > -/** - * Result object produced by a Lit query controller. - */ +/** Result object produced by a Lit query controller. */ export type QueryControllerResult< TData = unknown, TError = DefaultError, > = QueryObserverResult -/** - * Accessor-wrapped options accepted by `createInfiniteQueryController`. - */ +/** Accessor-wrapped options accepted by `createInfiniteQueryController`. */ export type InfiniteQueryControllerOptions< TQueryFnData = unknown, TError = DefaultError, @@ -48,9 +42,7 @@ export type InfiniteQueryControllerOptions< CreateInfiniteQueryOptions > -/** - * Accessor-wrapped options accepted by `createMutationController`. - */ +/** Accessor-wrapped options accepted by `createMutationController`. */ export type MutationControllerOptions< TData = unknown, TError = DefaultError, @@ -58,9 +50,7 @@ export type MutationControllerOptions< TOnMutateResult = unknown, > = Accessor> -/** - * Result object produced by a Lit mutation controller. - */ +/** Result object produced by a Lit mutation controller. */ export type MutationControllerResult< TData = unknown, TError = DefaultError, @@ -68,9 +58,7 @@ export type MutationControllerResult< TOnMutateResult = unknown, > = MutationObserverResult -/** - * Accessor-wrapped options accepted by `createQueriesController`. - */ +/** Accessor-wrapped options accepted by `createQueriesController`. */ export type QueriesControllerOptions< TQueryOptions extends Array = Array, TCombinedResult = CreateQueriesResults, diff --git a/packages/lit-query/src/useIsFetching.ts b/packages/lit-query/src/useIsFetching.ts index 4bd30cbaf35..289fd0ad080 100644 --- a/packages/lit-query/src/useIsFetching.ts +++ b/packages/lit-query/src/useIsFetching.ts @@ -116,27 +116,29 @@ class IsFetchingController extends BaseController { * When `filters` is a function, it is re-read during host updates so the count * can follow reactive host state. If `queryClient` is omitted, the controller * resolves the client from the nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the cache - * subscription. - * @param filters - Query filters, or a getter that returns query filters. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the current number of matching fetching queries. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { useIsFetching } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { useIsFetching } from '@tanstack/lit-query' * - * class TodosStatus extends LitElement { - * private readonly todosFetching = useIsFetching(this, { - * queryKey: ['todos'], - * }) + * class TodosStatus extends LitElement { + * private readonly todosFetching = useIsFetching(this, { + * queryKey: ['todos'], + * }) * - * render() { - * return html`${this.todosFetching()} active todo fetches` + * render() { + * return html`${this.todosFetching()} active todo fetches` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the cache + * subscription. + * @param filters - Query filters, or a getter that returns query filters. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the current number of matching fetching queries. */ export function useIsFetching( host: ReactiveControllerHost, diff --git a/packages/lit-query/src/useIsMutating.ts b/packages/lit-query/src/useIsMutating.ts index 1f8e10e8d6f..9665043c1f6 100644 --- a/packages/lit-query/src/useIsMutating.ts +++ b/packages/lit-query/src/useIsMutating.ts @@ -116,27 +116,29 @@ class IsMutatingController extends BaseController { * When `filters` is a function, it is re-read during host updates so the count * can follow reactive host state. If `queryClient` is omitted, the controller * resolves the client from the nearest connected `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the cache - * subscription. - * @param filters - Mutation filters, or a getter that returns mutation filters. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the current number of matching pending mutations. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { useIsMutating } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { useIsMutating } from '@tanstack/lit-query' * - * class MutationStatus extends LitElement { - * private readonly savesPending = useIsMutating(this, { - * mutationKey: ['save-project'], - * }) + * class MutationStatus extends LitElement { + * private readonly savesPending = useIsMutating(this, { + * mutationKey: ['save-project'], + * }) * - * render() { - * return html`${this.savesPending()} saves pending` + * render() { + * return html`${this.savesPending()} saves pending` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the cache + * subscription. + * @param filters - Mutation filters, or a getter that returns mutation filters. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the current number of matching pending mutations. */ export function useIsMutating( host: ReactiveControllerHost, diff --git a/packages/lit-query/src/useMutationState.ts b/packages/lit-query/src/useMutationState.ts index f60b9dd0c30..315f4d6ecf4 100644 --- a/packages/lit-query/src/useMutationState.ts +++ b/packages/lit-query/src/useMutationState.ts @@ -10,9 +10,7 @@ import type { } from '@tanstack/query-core' import type { ReactiveControllerHost } from 'lit' -/** - * Options accepted by `useMutationState`. - */ +/** Options accepted by `useMutationState`. */ export type MutationStateOptions = { /** Filters used to select mutations from the mutation cache. */ filters?: Accessor @@ -23,8 +21,8 @@ export type MutationStateOptions = { /** * Accessor returned by `useMutationState`. * - * Call the accessor or read its `current` property to get the selected state for - * matching mutations. + * Call the accessor or read its `current` property to get the selected state + * for matching mutations. */ export type MutationStateAccessor = ValueAccessor> & { /** Removes the controller from its Lit host and unsubscribes observers. */ @@ -160,28 +158,30 @@ class MutationStateController extends BaseController> { * the selection can follow reactive host state. If `queryClient` is omitted, * the controller resolves the client from the nearest connected * `QueryClientProvider`. - * @param host - The Lit reactive controller host that owns the mutation cache - * subscription. - * @param options - Mutation state filters and optional selector. - * @param queryClient - Optional explicit query client. Provide this for - * controllers that should not resolve a client from Lit context. - * @returns An accessor for the selected mutation state array. + * * @example - * ```ts - * import { LitElement, html } from 'lit' - * import { useMutationState } from '@tanstack/lit-query' + * ```ts + * import { LitElement, html } from 'lit' + * import { useMutationState } from '@tanstack/lit-query' * - * class PendingUploads extends LitElement { - * private readonly uploads = useMutationState(this, { - * filters: { mutationKey: ['upload'], status: 'pending' }, - * select: (mutation) => mutation.state.variables as File, - * }) + * class PendingUploads extends LitElement { + * private readonly uploads = useMutationState(this, { + * filters: { mutationKey: ['upload'], status: 'pending' }, + * select: (mutation) => mutation.state.variables as File, + * }) * - * render() { - * return html`${this.uploads().length} uploads pending` + * render() { + * return html`${this.uploads().length} uploads pending` + * } * } - * } - * ``` + * ``` + * + * @param host - The Lit reactive controller host that owns the mutation cache + * subscription. + * @param options - Mutation state filters and optional selector. + * @param queryClient - Optional explicit query client. Provide this for + * controllers that should not resolve a client from Lit context. + * @returns An accessor for the selected mutation state array. */ export function useMutationState< TResult = MutationState, diff --git a/packages/preact-query-devtools/src/PreactQueryDevtools.tsx b/packages/preact-query-devtools/src/PreactQueryDevtools.tsx index a74322a7416..57337fcf738 100644 --- a/packages/preact-query-devtools/src/PreactQueryDevtools.tsx +++ b/packages/preact-query-devtools/src/PreactQueryDevtools.tsx @@ -11,23 +11,23 @@ import type { QueryClient } from '@tanstack/preact-query' import type { VNode } from 'preact' /** - * The props of `PreactQueryDevtools`, which renders the devtools with a toggle button that opens - * them. + * The props of `PreactQueryDevtools`, which renders the devtools with a toggle + * button that opens them. */ export interface DevtoolsOptions { - /** - * Set this true if you want the dev tools to default to being open - */ + /** Set this true if you want the dev tools to default to being open */ initialIsOpen?: boolean /** * The position of the TanStack logo to open and close the devtools panel. * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'relative' + * * @defaultValue bottom-right */ buttonPosition?: DevtoolsButtonPosition /** - * The position of the Preact Query devtools panel. - * 'top' | 'bottom' | 'left' | 'right' + * The position of the Preact Query devtools panel. 'top' | 'bottom' | 'left' + * | 'right' + * * @defaultValue bottom */ position?: DevtoolsPosition @@ -36,35 +36,34 @@ export interface DevtoolsOptions { * nearest QueryClientProvider will be used. */ client?: QueryClient - /** - * Use this to provide custom error type handlers for the devtools panel. - */ + /** Use this to provide custom error type handlers for the devtools panel. */ errorTypes?: Array /** * Use this to pass a nonce to the style tag that is added to the document - * head. This is useful if you are using a Content Security Policy (CSP) - * nonce to allow inline styles. + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Use this to hide disabled queries from the devtools panel. - */ + /** Use this to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** * Use this to set the theme of the devtools panel. + * * @defaultValue system */ theme?: Theme } /** - * Renders the TanStack Query devtools, with a toggle button that opens them, for the given or - * nearest `QueryClient`. + * Renders the TanStack Query devtools, with a toggle button that opens them, + * for the given or nearest `QueryClient`. + * * @param props - The devtools options. * @returns The element the devtools are mounted in. */ diff --git a/packages/preact-query-devtools/src/PreactQueryDevtoolsPanel.tsx b/packages/preact-query-devtools/src/PreactQueryDevtoolsPanel.tsx index f90366d9989..d1621822c1d 100644 --- a/packages/preact-query-devtools/src/PreactQueryDevtoolsPanel.tsx +++ b/packages/preact-query-devtools/src/PreactQueryDevtoolsPanel.tsx @@ -6,7 +6,8 @@ import type { QueryClient } from '@tanstack/preact-query' import type { CSSProperties, VNode } from 'preact' /** - * The props of `PreactQueryDevtoolsPanel`, which renders the devtools panel inline. + * The props of `PreactQueryDevtoolsPanel`, which renders the devtools panel + * inline. */ export interface DevtoolsPanelOptions { /** @@ -14,42 +15,38 @@ export interface DevtoolsPanelOptions { * nearest QueryClientProvider will be used. */ client?: QueryClient - /** - * Custom error types to be shown in the devtools. - */ + /** Custom error types to be shown in the devtools. */ errorTypes?: Array /** * Use this to pass a nonce to the style tag that is added to the document - * head. This is useful if you are using a Content Security Policy (CSP) - * nonce to allow inline styles. + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Custom styles for the devtools panel container. - */ + /** Custom styles for the devtools panel container. */ style?: CSSProperties - /** - * Callback function when the devtools panel is closed. - */ + /** Callback function when the devtools panel is closed. */ onClose?: () => unknown - /** - * Use this to hide disabled queries from the devtools panel. - */ + /** Use this to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** * Use this to set the theme of the devtools panel. + * * @defaultValue system */ theme?: Theme } /** - * Renders the TanStack Query devtools panel inline, for the given or nearest `QueryClient`. + * Renders the TanStack Query devtools panel inline, for the given or nearest + * `QueryClient`. + * * @param props - The devtools panel options. * @returns The element the devtools panel is mounted in. */ diff --git a/packages/preact-query-devtools/src/index.ts b/packages/preact-query-devtools/src/index.ts index 13111cfd99a..04e95e90655 100644 --- a/packages/preact-query-devtools/src/index.ts +++ b/packages/preact-query-devtools/src/index.ts @@ -16,6 +16,7 @@ export const PreactQueryDevtoolsPanel: (typeof DevtoolsPanel)['PreactQueryDevtoo : DevtoolsPanel.PreactQueryDevtoolsPanel /** - * The props of `PreactQueryDevtoolsPanel`, which renders the devtools panel inline. + * The props of `PreactQueryDevtoolsPanel`, which renders the devtools panel + * inline. */ export type DevtoolsPanelOptions = DevtoolsPanel.DevtoolsPanelOptions diff --git a/packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx b/packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx index e3cae2a58d9..7b712a73fd0 100644 --- a/packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx +++ b/packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx @@ -16,8 +16,9 @@ import type { } from '@tanstack/preact-query' /** - * The props of `PersistQueryClientProvider`: the props of `QueryClientProvider`, plus the - * `persistOptions` and callbacks for when restoring succeeds or fails. + * The props of `PersistQueryClientProvider`: the props of + * `QueryClientProvider`, plus the `persistOptions` and callbacks for when + * restoring succeeds or fails. */ export type PersistQueryClientProviderProps = QueryClientProviderProps & { persistOptions: OmitKeyof @@ -26,13 +27,15 @@ export type PersistQueryClientProviderProps = QueryClientProviderProps & { } /** - * Provides the `QueryClient` like `QueryClientProvider`, and restores the persisted client first: - * while restoring, `useIsRestoring` returns `true` and queries wait for the restore to finish - * before subscribing. Once restored, the client is saved with the persister whenever the cache - * changes. - * @param props - The `QueryClientProvider` props, the `persistOptions`, and the `onSuccess` and - * `onError` callbacks. `onSuccess` is called once restoring finishes, even if nothing was restored - * (e.g. because the persisted client expired), and `onError` if restoring or `onSuccess` throws. + * Provides the `QueryClient` like `QueryClientProvider`, and restores the + * persisted client first: while restoring, `useIsRestoring` returns `true` and + * queries wait for the restore to finish before subscribing. Once restored, the + * client is saved with the persister whenever the cache changes. + * + * @param props - The `QueryClientProvider` props, the `persistOptions`, and the + * `onSuccess` and `onError` callbacks. `onSuccess` is called once restoring + * finishes, even if nothing was restored (e.g. because the persisted client + * expired), and `onError` if restoring or `onSuccess` throws. * @returns The `QueryClientProvider` wrapping the children. */ export const PersistQueryClientProvider = ({ diff --git a/packages/preact-query/src/HydrationBoundary.tsx b/packages/preact-query/src/HydrationBoundary.tsx index 893774a266f..659c0b5fc22 100644 --- a/packages/preact-query/src/HydrationBoundary.tsx +++ b/packages/preact-query/src/HydrationBoundary.tsx @@ -11,17 +11,11 @@ import type { QueryClient, } from '@tanstack/query-core' -/** - * The props accepted by `HydrationBoundary`. - */ +/** The props accepted by `HydrationBoundary`. */ export interface HydrationBoundaryProps { - /** - * The state to hydrate. - */ + /** The state to hydrate. */ state: DehydratedState | null | undefined - /** - * Optional. Note: unlike `hydrate`, `mutations` cannot be set here. - */ + /** Optional. Note: unlike `hydrate`, `mutations` cannot be set here. */ options?: OmitKeyof & { defaultOptions?: OmitKeyof< Exclude, @@ -29,59 +23,66 @@ export interface HydrationBoundaryProps { > } /** - * The components to render — always rendered unconditionally, not gated on hydration. New queries are - * hydrated into the cache during render; for queries that already exist in the cache, only newer dehydrated - * data is hydrated, and that happens in an effect after commit, so `children` may render briefly before it - * lands. + * The components to render — always rendered unconditionally, not gated on + * hydration. New queries are hydrated into the cache during render; for + * queries that already exist in the cache, only newer dehydrated data is + * hydrated, and that happens in an effect after commit, so `children` may + * render briefly before it lands. */ children?: ComponentChildren /** - * Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will be used. + * Use this to use a custom `QueryClient`. Otherwise, the one from the nearest + * context will be used. */ queryClient?: QueryClient } /** - * `HydrationBoundary` adds a previously dehydrated state into the `queryClient` that would be returned by - * `useQueryClient()`. If the client already contains data, the new queries will be intelligently merged based on - * update timestamp. + * `HydrationBoundary` adds a previously dehydrated state into the `queryClient` + * that would be returned by `useQueryClient()`. If the client already contains + * data, the new queries will be intelligently merged based on update + * timestamp. * * Note: Only `queries` can be dehydrated with an `HydrationBoundary`. - * @param props - The dehydrated `state` to hydrate, the hydrate `options`, an optional custom - * `queryClient`, and the `children` to render. - * @returns The provided `children`, rendered unconditionally. New queries in `state` are hydrated into the - * cache during render; for queries already in the cache, only newer dehydrated data is hydrated, in an effect - * after commit. + * * @example - * ```tsx - * import { HydrationBoundary } from '@tanstack/preact-query' + * ```tsx + * import { HydrationBoundary } from '@tanstack/preact-query' + * + * function App() { + * return ... + * } + * ``` * - * function App() { - * return ... - * } - * ``` * @example - * Server-side prefetch handed off to the client via `dehydrate`: - * ```tsx - * import { HydrationBoundary, dehydrate, noop } from '@tanstack/preact-query' + * Server-side prefetch handed off to the client via `dehydrate`: + * ```tsx + * import { HydrationBoundary, dehydrate, noop } from '@tanstack/preact-query' * - * async function ServerComponent() { + * async function ServerComponent() { * const queryClient = getQueryClient() * * await queryClient - * .query({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) - * .catch(noop) + * .query({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) + * .catch(noop) * * return ( - * - * - * + * + * + * * ) - * } - * ``` + * } + * ``` + * + * @param props - The dehydrated `state` to hydrate, the hydrate `options`, an + * optional custom `queryClient`, and the `children` to render. + * @returns The provided `children`, rendered unconditionally. New queries in + * `state` are hydrated into the cache during render; for queries already in + * the cache, only newer dehydrated data is hydrated, in an effect after + * commit. */ export const HydrationBoundary = ({ children, diff --git a/packages/preact-query/src/IsRestoringProvider.ts b/packages/preact-query/src/IsRestoringProvider.ts index 577271c5fd3..db3bcc0380d 100644 --- a/packages/preact-query/src/IsRestoringProvider.ts +++ b/packages/preact-query/src/IsRestoringProvider.ts @@ -4,15 +4,18 @@ import { useContext } from 'preact/hooks' const IsRestoringContext = createContext(false) /** - * If you are using `PersistQueryClientProvider`, you can also use the `useIsRestoring` hook alongside it to - * check if a restore is currently in progress. `useQuery` and friends also check this internally to avoid - * race conditions between the restore and mounting queries. - * @returns `true` while a persisted client is being restored, `false` otherwise. + * If you are using `PersistQueryClientProvider`, you can also use the + * `useIsRestoring` hook alongside it to check if a restore is currently in + * progress. `useQuery` and friends also check this internally to avoid race + * conditions between the restore and mounting queries. + * + * @returns `true` while a persisted client is being restored, `false` + * otherwise. */ export const useIsRestoring = () => useContext(IsRestoringContext) /** - * The Provider that `PersistQueryClientProvider` uses to signal whether a persisted client is currently - * being restored, read by `useIsRestoring`. + * The Provider that `PersistQueryClientProvider` uses to signal whether a + * persisted client is currently being restored, read by `useIsRestoring`. */ export const IsRestoringProvider = IsRestoringContext.Provider diff --git a/packages/preact-query/src/QueryClientProvider.tsx b/packages/preact-query/src/QueryClientProvider.tsx index 4cfc74eb844..87880faa4bd 100644 --- a/packages/preact-query/src/QueryClientProvider.tsx +++ b/packages/preact-query/src/QueryClientProvider.tsx @@ -4,7 +4,8 @@ import type { QueryClient } from '@tanstack/query-core' import type { ComponentChildren, VNode } from 'preact' /** - * The context that `useQueryClient` reads from. `QueryClientProvider` is the normal way to set it. + * The context that `useQueryClient` reads from. `QueryClientProvider` is the + * normal way to set it. */ export const QueryClientContext = createContext( undefined, @@ -12,11 +13,12 @@ export const QueryClientContext = createContext( /** * The `useQueryClient` hook returns the current `QueryClient` instance. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. + * + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. * @returns The current `QueryClient` instance. - * @throws {Error} If no `queryClient` argument is passed and no `QueryClientProvider` is found in the - * component tree. + * @throws {Error} If no `queryClient` argument is passed and no + * `QueryClientProvider` is found in the component tree. */ export const useQueryClient = (queryClient?: QueryClient) => { const client = useContext(QueryClientContext) @@ -32,9 +34,7 @@ export const useQueryClient = (queryClient?: QueryClient) => { return client } -/** - * The props accepted by `QueryClientProvider`. - */ +/** The props accepted by `QueryClientProvider`. */ export type QueryClientProviderProps = { /** * **Required** @@ -42,29 +42,34 @@ export type QueryClientProviderProps = { * The `QueryClient` instance to provide. */ client: QueryClient - /** - * The components that get access to the provided `QueryClient`. - */ + /** The components that get access to the provided `QueryClient`. */ children?: ComponentChildren } /** - * Use the `QueryClientProvider` component to connect and provide a `QueryClient` to your application. Also - * calls `client.mount()`/`client.unmount()` as this component mounts/unmounts, which subscribes the client to - * focus/online events (resuming any paused mutations and refetching as needed when the app regains focus or - * comes back online). - * @param props - The `client` to provide, and the `children` that get access to it. - * @returns The provided `children`, wrapped so they can read the `QueryClient` via `useQueryClient`. + * Use the `QueryClientProvider` component to connect and provide a + * `QueryClient` to your application. Also calls + * `client.mount()`/`client.unmount()` as this component mounts/unmounts, which + * subscribes the client to focus/online events (resuming any paused mutations + * and refetching as needed when the app regains focus or comes back online). + * * @example - * ```tsx - * import { QueryClient, QueryClientProvider } from '@tanstack/preact-query' + * ```tsx + * import { QueryClient, QueryClientProvider } from '@tanstack/preact-query' + * + * const queryClient = new QueryClient() * - * const queryClient = new QueryClient() + * function App() { + * return ( + * ... + * ) + * } + * ``` * - * function App() { - * return ... - * } - * ``` + * @param props - The `client` to provide, and the `children` that get access to + * it. + * @returns The provided `children`, wrapped so they can read the `QueryClient` + * via `useQueryClient`. */ export const QueryClientProvider = ({ client, diff --git a/packages/preact-query/src/QueryErrorResetBoundary.tsx b/packages/preact-query/src/QueryErrorResetBoundary.tsx index 9f5e1045a9a..7c9d00ceafd 100644 --- a/packages/preact-query/src/QueryErrorResetBoundary.tsx +++ b/packages/preact-query/src/QueryErrorResetBoundary.tsx @@ -5,42 +5,43 @@ import type { ComponentChildren } from 'preact' // CONTEXT /** - * Resets any query errors within the boundary, so queries know they can try again. + * Resets any query errors within the boundary, so queries know they can try + * again. */ export type QueryErrorResetFunction = () => void -/** - * Returns whether the boundary has been reset and not yet cleared. - */ +/** Returns whether the boundary has been reset and not yet cleared. */ export type QueryErrorIsResetFunction = () => boolean /** - * Clears the reset state, so queries know not to try again until the boundary is reset again. + * Clears the reset state, so queries know not to try again until the boundary + * is reset again. */ export type QueryErrorClearResetFunction = () => void /** - * The value a `QueryErrorResetBoundary` shares through context, used to reset query errors within - * it and to check whether a reset was requested. + * The value a `QueryErrorResetBoundary` shares through context, used to reset + * query errors within it and to check whether a reset was requested. */ export interface QueryErrorResetBoundaryValue { /** - * Clears the reset state, so queries know not to try again until the boundary is reset again. + * Clears the reset state, so queries know not to try again until the boundary + * is reset again. */ clearReset: QueryErrorClearResetFunction - /** - * Returns whether the boundary has been reset and not yet cleared. - */ + /** Returns whether the boundary has been reset and not yet cleared. */ isReset: QueryErrorIsResetFunction /** - * Resets any query errors within the boundary, so queries know they can try again. + * Resets any query errors within the boundary, so queries know they can try + * again. */ reset: QueryErrorResetFunction } /** - * Creates the value shared through the boundary's context, which tracks whether a reset was - * requested. + * Creates the value shared through the boundary's context, which tracks whether + * a reset was requested. + * * @returns The `clearReset`, `isReset`, and `reset` functions of the boundary. */ function createValue(): QueryErrorResetBoundaryValue { @@ -63,31 +64,34 @@ const QueryErrorResetBoundaryContext = createContext(createValue()) // HOOK /** - * This hook will reset any query errors within the closest `QueryErrorResetBoundary`. If there is no boundary - * defined it will reset them globally. - * @returns The boundary's {@link QueryErrorResetBoundaryValue}. + * This hook will reset any query errors within the closest + * `QueryErrorResetBoundary`. If there is no boundary defined it will reset them + * globally. + * * @example - * ```tsx - * import { useErrorBoundary } from 'preact/hooks' - * import type { ComponentChildren } from 'preact' - * import { useQueryErrorResetBoundary } from '@tanstack/preact-query' + * ```tsx + * import { useErrorBoundary } from 'preact/hooks' + * import type { ComponentChildren } from 'preact' + * import { useQueryErrorResetBoundary } from '@tanstack/preact-query' * - * function App({ children }: { children: ComponentChildren }) { - * const { reset } = useQueryErrorResetBoundary() - * const [error, resetError] = useErrorBoundary(() => reset()) + * function App({ children }: { children: ComponentChildren }) { + * const { reset } = useQueryErrorResetBoundary() + * const [error, resetError] = useErrorBoundary(() => reset()) * - * if (error) { - * return ( - *
- * There was an error! - * - *
- * ) + * if (error) { + * return ( + *
+ * There was an error! + * + *
+ * ) + * } + * + * return children * } + * ``` * - * return children - * } - * ``` + * @returns The boundary's {@link QueryErrorResetBoundaryValue}. */ export const useQueryErrorResetBoundary = () => useContext(QueryErrorResetBoundaryContext) @@ -96,6 +100,7 @@ export const useQueryErrorResetBoundary = () => /** * A render-prop function usable as `children` on `QueryErrorResetBoundary`. + * * @param value - The boundary's {@link QueryErrorResetBoundaryValue}. * @returns The children to render. */ @@ -103,63 +108,64 @@ export type QueryErrorResetBoundaryFunction = ( value: QueryErrorResetBoundaryValue, ) => ComponentChildren -/** - * The props accepted by `QueryErrorResetBoundary`. - */ +/** The props accepted by `QueryErrorResetBoundary`. */ export interface QueryErrorResetBoundaryProps { /** - * Either a plain node, or a function that receives the boundary's {@link QueryErrorResetBoundaryValue} and - * returns a node. + * Either a plain node, or a function that receives the boundary's + * {@link QueryErrorResetBoundaryValue} and returns a node. */ children: QueryErrorResetBoundaryFunction | ComponentChildren } /** - * When using `suspense` or `throwOnError` in your queries, you need a way to let queries know that you want to - * try again when re-rendering after some error occurred. With the `QueryErrorResetBoundary` component you can - * reset any query errors within the boundaries of the component. - * @param props - The `children` to render. - * @returns The `children`, rendered as-is, or called with the boundary's {@link QueryErrorResetBoundaryValue} - * if `children` is a function. - * @example - * ```tsx - * import { useErrorBoundary } from 'preact/hooks' - * import type { ComponentChildren } from 'preact' - * import { QueryErrorResetBoundary } from '@tanstack/preact-query' - * - * function App() { - * return ( - * - * {({ reset }) => ( - * - * - * - * )} - * - * ) - * } + * When using `suspense` or `throwOnError` in your queries, you need a way to + * let queries know that you want to try again when re-rendering after some + * error occurred. With the `QueryErrorResetBoundary` component you can reset + * any query errors within the boundaries of the component. * - * function ErrorBoundary({ - * children, - * reset, - * }: { - * children: ComponentChildren - * reset: () => void - * }) { - * const [error, resetError] = useErrorBoundary(() => reset()) + * @example + * ```tsx + * import { useErrorBoundary } from 'preact/hooks' + * import type { ComponentChildren } from 'preact' + * import { QueryErrorResetBoundary } from '@tanstack/preact-query' * - * if (error) { + * function App() { * return ( - *
- * There was an error! - * - *
+ * + * {({ reset }) => ( + * + * + * + * )} + * * ) * } * - * return children - * } - * ``` + * function ErrorBoundary({ + * children, + * reset, + * }: { + * children: ComponentChildren + * reset: () => void + * }) { + * const [error, resetError] = useErrorBoundary(() => reset()) + * + * if (error) { + * return ( + *
+ * There was an error! + * + *
+ * ) + * } + * + * return children + * } + * ``` + * + * @param props - The `children` to render. + * @returns The `children`, rendered as-is, or called with the boundary's + * {@link QueryErrorResetBoundaryValue} if `children` is a function. */ export const QueryErrorResetBoundary = ({ children, diff --git a/packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundary.ts b/packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundary.ts index 2d8de273543..8c31f682d17 100644 --- a/packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundary.ts +++ b/packages/preact-query/src/__tests__/ErrorBoundary/ErrorBoundary.ts @@ -49,9 +49,8 @@ export class ErrorBoundary extends Component< override componentDidCatch(error: Error, info: ErrorInfo) { /** - * To emulate the react behavior of console.error - * we add one here to show that the errors bubble up - * to the system and can be seen in the console + * To emulate the react behavior of console.error we add one here to show + * that the errors bubble up to the system and can be seen in the console */ console.error('%o\n\n%s', error, info) this.props.onError?.(error, info) diff --git a/packages/preact-query/src/__tests__/ErrorBoundary/index.ts b/packages/preact-query/src/__tests__/ErrorBoundary/index.ts index 51ee3ea0dff..53153e722d4 100644 --- a/packages/preact-query/src/__tests__/ErrorBoundary/index.ts +++ b/packages/preact-query/src/__tests__/ErrorBoundary/index.ts @@ -1,7 +1,7 @@ /** - * Custom Error Boundary port from 'react-error-boundary' - * Taken directly from https://github.com/bvaughn/react-error-boundary/ - * and modified to server a preact use case + * Custom Error Boundary port from 'react-error-boundary' Taken directly from + * https://github.com/bvaughn/react-error-boundary/ and modified to server a + * preact use case */ export * from './ErrorBoundary' diff --git a/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx b/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx index c33bcb97bc3..30684f4f4b3 100644 --- a/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx +++ b/packages/preact-query/src/__tests__/useSuspenseQuery.test.tsx @@ -38,10 +38,10 @@ describe('useSuspenseQuery', () => { }) /** - * Preact Suspense handles the rerenders differently than React. - * This test only checks for 4 renders (vs. React -> 6) - * so, instead of state change reacting and updating (and also losing the state) - * we abstract out the suspense + * Preact Suspense handles the rerenders differently than React. This test + * only checks for 4 renders (vs. React -> 6) so, instead of state change + * reacting and updating (and also losing the state) we abstract out the + * suspense */ it('should render correctly when state is lifted above Suspense', async () => { const states: Array> = [] diff --git a/packages/preact-query/src/errorBoundaryUtils.ts b/packages/preact-query/src/errorBoundaryUtils.ts index 03d7fa8629a..b84e1dce5f7 100644 --- a/packages/preact-query/src/errorBoundaryUtils.ts +++ b/packages/preact-query/src/errorBoundaryUtils.ts @@ -11,12 +11,16 @@ import type { import type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary' /** - * Turns off `retryOnMount` for a query that throws its errors (with `suspense` or `throwOnError`), - * unless the error boundary has been reset, so a remount doesn't retry the failed query before the - * user resets the boundary. Mutates the options. + * Turns off `retryOnMount` for a query that throws its errors (with `suspense` + * or `throwOnError`), unless the error boundary has been reset, so a remount + * doesn't retry the failed query before the user resets the boundary. Mutates + * the options. + * * @param options - The defaulted query options to adjust. - * @param errorResetBoundary - The value of the nearest `QueryErrorResetBoundary`. - * @param query - The query, used to evaluate a `throwOnError` function against its error. + * @param errorResetBoundary - The value of the nearest + * `QueryErrorResetBoundary`. + * @param query - The query, used to evaluate a `throwOnError` function against + * its error. */ export const ensurePreventErrorBoundaryRetry = < TQueryFnData, @@ -53,9 +57,11 @@ export const ensurePreventErrorBoundaryRetry = < } /** - * Clears the reset state of the error boundary after the component mounts, so later errors are - * thrown to the boundary again. - * @param errorResetBoundary - The value of the nearest `QueryErrorResetBoundary`. + * Clears the reset state of the error boundary after the component mounts, so + * later errors are thrown to the boundary again. + * + * @param errorResetBoundary - The value of the nearest + * `QueryErrorResetBoundary`. */ export const useClearResetErrorBoundary = ( errorResetBoundary: QueryErrorResetBoundaryValue, @@ -66,11 +72,13 @@ export const useClearResetErrorBoundary = ( } /** - * Checks whether the query error should be thrown to the nearest error boundary: the query errored - * and isn't fetching, the boundary hasn't been reset, and either `suspense` is enabled with no data - * or `throwOnError` says so. - * @param params - The observer `result`, the `errorResetBoundary`, the `throwOnError` option, the - * `query`, and the `suspense` option. + * Checks whether the query error should be thrown to the nearest error + * boundary: the query errored and isn't fetching, the boundary hasn't been + * reset, and either `suspense` is enabled with no data or `throwOnError` says + * so. + * + * @param params - The observer `result`, the `errorResetBoundary`, the + * `throwOnError` option, the `query`, and the `suspense` option. * @returns `true` if the error should be thrown. */ export const getHasError = < diff --git a/packages/preact-query/src/infiniteQueryOptions.ts b/packages/preact-query/src/infiniteQueryOptions.ts index 29b7f6130d8..20add019767 100644 --- a/packages/preact-query/src/infiniteQueryOptions.ts +++ b/packages/preact-query/src/infiniteQueryOptions.ts @@ -12,14 +12,19 @@ import type { import type { UseInfiniteQueryOptions } from './types' /** - * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data` - * may be `undefined` while the query is `pending`. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UndefinedInitialDataInfiniteOptions< TQueryFnData, @@ -35,11 +40,12 @@ export type UndefinedInitialDataInfiniteOptions< TPageParam > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData?: | undefined @@ -50,15 +56,20 @@ export type UndefinedInitialDataInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set and - * `queryFn` is not `skipToken` — same as {@link UndefinedInitialDataInfiniteOptions}, but `queryFn` may not be + * The options accepted by the `infiniteQueryOptions` overload selected when no + * `initialData` is set and `queryFn` is not `skipToken` — same as + * {@link UndefinedInitialDataInfiniteOptions}, but `queryFn` may not be * `skipToken`. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UnusedSkipTokenInfiniteOptions< TQueryFnData, @@ -71,10 +82,12 @@ export type UnusedSkipTokenInfiniteOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If - * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a - * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been - * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own. + * `skipToken` is not allowed as a value here — this overload is selected when + * no `initialData` is set. If you don't intend to run the query yet, set + * `enabled: false` — omitting `queryFn` alone still triggers a fetch that + * fails with "Missing queryFn" unless `enabled` is `false` or a default query + * function has been defined. A default query function only supplies + * `queryFn`; it doesn't defer the fetch on its own. */ queryFn?: Exclude< UseInfiniteQueryOptions< @@ -89,14 +102,19 @@ export type UnusedSkipTokenInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is - * never `undefined` (unless a `select` changes `TData` to include `undefined`). - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type DefinedInitialDataInfiniteOptions< TQueryFnData, @@ -112,11 +130,12 @@ export type DefinedInitialDataInfiniteOptions< TPageParam > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData: | NonUndefinedGuard> @@ -125,43 +144,54 @@ export type DefinedInitialDataInfiniteOptions< } /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`. - * These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`. - * `options.queryKey` is required and is the query key to generate options for. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `useInfiniteQuery`. These options can be shared across hooks and + * imperative APIs such as `queryClient.infiniteQuery`. `options.queryKey` is + * required and is the query key to generate options for. * * This overload is selected when `initialData` is set. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`, with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link useInfiniteQuery} for examples that fetch further pages, from a button click or - * automatically as the user scrolls. - * @see {@link useInfiniteQuery} to run an infinite query with these options. + * + * @remarks + * See {@link useInfiniteQuery} for examples that fetch further pages, from a + * button click or automatically as the user scrolls. * @example - * ```tsx - * import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/preact-query' + * ```tsx + * import { + * infiniteQueryOptions, + * useInfiniteQuery, + * } from '@tanstack/preact-query' * - * export const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * }) + * export const projectsOptions = infiniteQueryOptions({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, + * }) * - * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery(projectsOptions) + * function Projects() { + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery(projectsOptions) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => page.projects.map((p) =>
  • {p.name}
  • ))} - *
- *
- * ) - * } - * ``` + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) + * } + * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -187,40 +217,46 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`. - * These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`. - * `options.queryKey` is required and is the query key to generate options for. - * @param options - The {@link UnusedSkipTokenInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link useInfiniteQuery} for examples that fetch further pages, from a button click or - * automatically as the user scrolls. - * @see {@link useInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `useInfiniteQuery`. These options can be shared across hooks and + * imperative APIs such as `queryClient.infiniteQuery`. `options.queryKey` is + * required and is the query key to generate options for. + * + * @remarks + * See {@link useInfiniteQuery} for examples that fetch further pages, from a + * button click or automatically as the user scrolls. * @example - * A parameterized factory, so the same options object can be reused per `postId`: - * ```tsx - * import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/preact-query' + * A parameterized factory, so the same options object can be reused per `postId`: + * ```tsx + * import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/preact-query' * - * export const commentsOptions = (postId: string) => + * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ - * queryKey: ['post', postId, 'comments'], - * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', postId, 'comments'], + * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * - * function Comments({ postId }: { postId: string }) { + * function Comments({ postId }: { postId: string }) { * const { data, isPending, isError, error } = useInfiniteQuery(commentsOptions(postId)) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - *
    - * {data.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} - *
+ *
    + * {data.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UnusedSkipTokenInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -246,40 +282,47 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`. - * These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`. - * `options.queryKey` is required and is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks See {@link useInfiniteQuery} for examples that fetch further pages (from a button click or - * automatically as the user scrolls) and that use `skipToken` to disable the query until `postId` is set. - * @see {@link useInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `useInfiniteQuery`. These options can be shared across hooks and + * imperative APIs such as `queryClient.infiniteQuery`. `options.queryKey` is + * required and is the query key to generate options for. + * + * @remarks + * See {@link useInfiniteQuery} for examples that fetch further pages (from a + * button click or automatically as the user scrolls) and that use `skipToken` + * to disable the query until `postId` is set. * @example - * A parameterized factory, so the same options object can be reused per `postId`: - * ```tsx - * import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/preact-query' + * A parameterized factory, so the same options object can be reused per `postId`: + * ```tsx + * import { infiniteQueryOptions, useInfiniteQuery } from '@tanstack/preact-query' * - * export const commentsOptions = (postId: string) => + * export const commentsOptions = (postId: string) => * infiniteQueryOptions({ - * queryKey: ['post', postId, 'comments'], - * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', postId, 'comments'], + * queryFn: ({ pageParam }) => fetchComments(postId, pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * - * function Comments({ postId }: { postId: string }) { + * function Comments({ postId }: { postId: string }) { * const { data, isPending, isError, error } = useInfiniteQuery(commentsOptions(postId)) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - *
    - * {data.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} - *
+ *
    + * {data.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, diff --git a/packages/preact-query/src/mutationOptions.ts b/packages/preact-query/src/mutationOptions.ts index ac798ee0f44..68c3245b8ba 100644 --- a/packages/preact-query/src/mutationOptions.ts +++ b/packages/preact-query/src/mutationOptions.ts @@ -3,31 +3,33 @@ import type { DefaultError, WithRequired } from '@tanstack/query-core' import type { UseMutationOptions } from './types' /** - * You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. A - * `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with - * `useMutationState`. - * @param options - The mutation options to use, identical to what you'd pass to `useMutation`, with a - * required `mutationKey`. - * @returns The same options object, unchanged. - * @see {@link useMutation} to run the mutation these options describe. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `useMutation`. A `mutationKey` is required on this overload so the + * mutation can be looked up later, e.g. with `useMutationState`. + * * @example - * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: - * ```tsx - * import { mutationOptions, useMutationState } from '@tanstack/preact-query' + * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: + * ```tsx + * import { mutationOptions, useMutationState } from '@tanstack/preact-query' * - * const createPostOptions = mutationOptions({ + * const createPostOptions = mutationOptions({ * mutationKey: ['posts', 'create'], * mutationFn: createPost, - * }) + * }) * - * function SavingIndicator() { + * function SavingIndicator() { * const isCreatingPost = useMutationState({ - * filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' }, + * filters: { mutationKey: createPostOptions.mutationKey, status: 'pending' }, * }).length > 0 * * return isCreatingPost ? Saving… : null - * } - * ``` + * } + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `useMutation`, with a required `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, @@ -44,28 +46,37 @@ export function mutationOptions< 'mutationKey' > /** - * You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. No - * `mutationKey` is required on this overload — use this when you don't need to target the mutation via a - * `mutationKey` filter later (e.g. with `useMutationState`); it can still be observed through other filters, - * such as `status`. - * @param options - The mutation options to use, identical to what you'd pass to `useMutation`, without a - * `mutationKey`. - * @returns The same options object, unchanged. - * @remarks See the other overload's example for looking a mutation up via `useMutationState`. - * @see {@link useMutation} to run the mutation these options describe. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `useMutation`. No `mutationKey` is required on this overload — use this + * when you don't need to target the mutation via a `mutationKey` filter later + * (e.g. with `useMutationState`); it can still be observed through other + * filters, such as `status`. + * + * @remarks + * See the other overload's example for looking a mutation up via + * `useMutationState`. * @example - * ```tsx - * import { mutationOptions, useMutation } from '@tanstack/preact-query' + * ```tsx + * import { mutationOptions, useMutation } from '@tanstack/preact-query' * - * export const createPostOptions = mutationOptions({ - * mutationFn: createPost, - * }) + * export const createPostOptions = mutationOptions({ + * mutationFn: createPost, + * }) * - * function CreatePost() { - * const mutation = useMutation(createPostOptions) - * return - * } - * ``` + * function CreatePost() { + * const mutation = useMutation(createPostOptions) + * return ( + * + * ) + * } + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `useMutation`, without a `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, diff --git a/packages/preact-query/src/queryOptions.ts b/packages/preact-query/src/queryOptions.ts index 3d616841393..be75d5f9585 100644 --- a/packages/preact-query/src/queryOptions.ts +++ b/packages/preact-query/src/queryOptions.ts @@ -12,8 +12,10 @@ import type { import type { UseQueryOptions } from './types' /** - * The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be - * `undefined` while the query is `pending`. + * The options accepted by the `queryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -26,11 +28,12 @@ export type UndefinedInitialDataOptions< TQueryKey extends QueryKey = QueryKey, > = UseQueryOptions & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData?: | undefined @@ -39,8 +42,10 @@ export type UndefinedInitialDataOptions< } /** - * The options accepted by the `queryOptions` overload selected when no `initialData` is set and `queryFn` is - * not `skipToken` — same as {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`. + * The options accepted by the `queryOptions` overload selected when no + * `initialData` is set and `queryFn` is not `skipToken` — same as + * {@link UndefinedInitialDataOptions}, but `queryFn` may not be `skipToken`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -56,10 +61,12 @@ export type UnusedSkipTokenOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — this overload is selected when no `initialData` is set. If - * you don't intend to run the query yet, set `enabled: false` — omitting `queryFn` alone still triggers a - * fetch that fails with "Missing queryFn" unless `enabled` is `false` or a default query function has been - * defined. A default query function only supplies `queryFn`; it doesn't defer the fetch on its own. + * `skipToken` is not allowed as a value here — this overload is selected when + * no `initialData` is set. If you don't intend to run the query yet, set + * `enabled: false` — omitting `queryFn` alone still triggers a fetch that + * fails with "Missing queryFn" unless `enabled` is `false` or a default query + * function has been defined. A default query function only supplies + * `queryFn`; it doesn't defer the fetch on its own. */ queryFn?: Exclude< UseQueryOptions['queryFn'], @@ -68,8 +75,10 @@ export type UnusedSkipTokenOptions< } /** - * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never - * `undefined` (unless a `select` changes `TData` to include `undefined`). + * The options accepted by the `queryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -82,59 +91,70 @@ export type DefinedInitialDataOptions< TQueryKey extends QueryKey = QueryKey, > = Omit, 'queryFn'> & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData: | NonUndefinedGuard | (() => NonUndefinedGuard) /** - * Optional here, but omitting it is only safe when no fetch will be attempted — for example with - * `enabled: false`, or when a default query function has been defined. Otherwise, an enabled query with no - * `queryFn` still tries to fetch and fails with a "Missing queryFn" error; `initialData` does not prevent this. + * Optional here, but omitting it is only safe when no fetch will be attempted + * — for example with `enabled: false`, or when a default query function has + * been defined. Otherwise, an enabled query with no `queryFn` still tries to + * fetch and fails with a "Missing queryFn" error; `initialData` does not + * prevent this. */ queryFn?: QueryFunction } /** - * You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can - * be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and - * is the query key to generate options for. - * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `useQuery`, with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. + * You can generally pass everything to `queryOptions` that you can also pass to + * `useQuery`. These options can be shared across hooks and imperative APIs such + * as `queryClient.query`. `options.queryKey` is required and is the query key + * to generate options for. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). + * + * @example + * ```tsx + * import { queryOptions, useQuery } from '@tanstack/preact-query' + * + * export const postsOptions = queryOptions({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * }) + * + * function Posts() { + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery(postsOptions) + * + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) + * } + * ``` + * + * @param options - The {@link DefinedInitialDataOptions} to use — everything + * you can pass to `useQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. * @see {@link useQuery} to run a query with these options. * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. - * @example - * ```tsx - * import { queryOptions, useQuery } from '@tanstack/preact-query' - * - * export const postsOptions = queryOptions({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * }) - * - * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery(postsOptions) - * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) =>
  • {post.title}
  • )} - *
- *
- * ) - * } - * ``` */ export function queryOptions< TQueryFnData = unknown, @@ -147,33 +167,38 @@ export function queryOptions< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can - * be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and - * is the query key to generate options for. - * @param options - The {@link UnusedSkipTokenOptions} to use — everything you can pass to `useQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link useQuery} to run a query with these options. - * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + * You can generally pass everything to `queryOptions` that you can also pass to + * `useQuery`. These options can be shared across hooks and imperative APIs such + * as `queryClient.query`. `options.queryKey` is required and is the query key + * to generate options for. + * * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```tsx - * import { queryOptions, useQuery } from '@tanstack/preact-query' + * A parameterized factory, so the same options object can be reused per `id`: + * ```tsx + * import { queryOptions, useQuery } from '@tanstack/preact-query' * - * export const postOptions = (id: string) => + * export const postOptions = (id: string) => * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), * }) * - * function Post({ id }: { id: string }) { + * function Post({ id }: { id: string }) { * const { data, isPending, isError, error } = useQuery(postOptions(id)) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return

{data.title}

- * } - * ``` + * } + * ``` + * + * @param options - The {@link UnusedSkipTokenOptions} to use — everything you + * can pass to `useQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useQuery} to run a query with these options. + * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. */ export function queryOptions< TQueryFnData = unknown, @@ -186,46 +211,46 @@ export function queryOptions< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can - * be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and - * is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `useQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @remarks This is the only overload that accepts `queryFn: skipToken`, shown below. - * @see {@link useQuery} to run a query with these options. - * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. + * You can generally pass everything to `queryOptions` that you can also pass to + * `useQuery`. These options can be shared across hooks and imperative APIs such + * as `queryClient.query`. `options.queryKey` is required and is the query key + * to generate options for. + * + * @remarks + * This is the only overload that accepts `queryFn: skipToken`, shown below. * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```tsx - * import { queryOptions, useQuery } from '@tanstack/preact-query' + * A parameterized factory, so the same options object can be reused per `id`: + * ```tsx + * import { queryOptions, useQuery } from '@tanstack/preact-query' * - * export const postOptions = (id: string) => + * export const postOptions = (id: string) => * queryOptions({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), * }) * - * function Post({ id }: { id: string }) { + * function Post({ id }: { id: string }) { * const { data, isPending, isError, error } = useQuery(postOptions(id)) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return

{data.title}

- * } - * ``` + * } + * ``` + * * @example - * A factory that disables the query, type safe, until `postId` is set: - * ```tsx - * import { queryOptions, skipToken, useQuery } from '@tanstack/preact-query' + * A factory that disables the query, type safe, until `postId` is set: + * ```tsx + * import { queryOptions, skipToken, useQuery } from '@tanstack/preact-query' * - * export const postOptions = (postId: number | undefined) => + * export const postOptions = (postId: number | undefined) => * queryOptions({ - * queryKey: ['post', postId], - * queryFn: postId != null ? () => fetchPost(postId) : skipToken, + * queryKey: ['post', postId], + * queryFn: postId != null ? () => fetchPost(postId) : skipToken, * }) * - * function Post({ postId }: { postId: number | undefined }) { + * function Post({ postId }: { postId: number | undefined }) { * const { data, isLoading, isError, error } = useQuery(postOptions(postId)) * * if (postId == null) return 'Select a post' @@ -233,8 +258,15 @@ export function queryOptions< * if (isError) return Error: {error.message} * * return

{data?.title}

- * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataOptions} to use — everything + * you can pass to `useQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useQuery} to run a query with these options. + * @see [The Query Options API](https://tkdodo.eu/blog/the-query-options-api) for more on this pattern. */ export function queryOptions< TQueryFnData = unknown, diff --git a/packages/preact-query/src/suspense.ts b/packages/preact-query/src/suspense.ts index 540579955f9..72ca6b95e22 100644 --- a/packages/preact-query/src/suspense.ts +++ b/packages/preact-query/src/suspense.ts @@ -10,8 +10,9 @@ import type { import type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary' /** - * The default `throwOnError` of the suspense hooks: throws the error to the nearest error boundary - * only if the query has no data to show. + * The default `throwOnError` of the suspense hooks: throws the error to the + * nearest error boundary only if the query has no data to show. + * * @param _error - The error of the query. Unused. * @param query - The query that errored. * @returns `true` if the query has no data. @@ -27,9 +28,11 @@ export const defaultThrowOnError = < ) => query.state.data === undefined /** - * Raises `staleTime` and a numeric `gcTime` to at least 1000ms when `suspense` is enabled, so a - * component that remounts after suspending doesn't refetch right away or find the query garbage - * collected. A `'static'` `staleTime` is kept as is. Mutates the options. + * Raises `staleTime` and a numeric `gcTime` to at least 1000ms when `suspense` + * is enabled, so a component that remounts after suspending doesn't refetch + * right away or find the query garbage collected. A `'static'` `staleTime` is + * kept as is. Mutates the options. + * * @param defaultedOptions - The defaulted query options to adjust. */ export const ensureSuspenseTimers = ( @@ -61,7 +64,9 @@ export const ensureSuspenseTimers = ( } /** - * Checks whether a query should suspend: `suspense` is enabled and the result is still `pending`. + * Checks whether a query should suspend: `suspense` is enabled and the result + * is still `pending`. + * * @param defaultedOptions - The defaulted query options, if any. * @param result - The current result of the observer. * @returns `true` if the component should suspend. @@ -74,11 +79,14 @@ export const shouldSuspend = ( ) => defaultedOptions?.suspense && result.isPending /** - * Fetches the query for a suspending component, without affecting the observer's own result. If - * the fetch fails, the reset state of the error boundary is cleared, so the error is thrown to it. + * Fetches the query for a suspending component, without affecting the + * observer's own result. If the fetch fails, the reset state of the error + * boundary is cleared, so the error is thrown to it. + * * @param defaultedOptions - The defaulted query options to fetch with. * @param observer - The observer of the query. - * @param errorResetBoundary - The value of the nearest `QueryErrorResetBoundary`. + * @param errorResetBoundary - The value of the nearest + * `QueryErrorResetBoundary`. * @returns A promise that resolves once the fetch settles. It never rejects. */ export const fetchOptimistic = < diff --git a/packages/preact-query/src/types.ts b/packages/preact-query/src/types.ts index a9fd8822693..4f49b24ba89 100644 --- a/packages/preact-query/src/types.ts +++ b/packages/preact-query/src/types.ts @@ -21,8 +21,9 @@ import type { } from '@tanstack/query-core' /** - * {@link UseBaseQueryOptions} with all type parameters set to `any`, useful when the specific types aren't - * relevant, e.g. when accepting options for any query in a helper function. + * {@link UseBaseQueryOptions} with all type parameters set to `any`, useful when + * the specific types aren't relevant, e.g. when accepting options for any query + * in a helper function. */ export type AnyUseBaseQueryOptions = UseBaseQueryOptions< any, @@ -32,14 +33,17 @@ export type AnyUseBaseQueryOptions = UseBaseQueryOptions< any > /** - * The options shared by `useQuery` and `useSuspenseQuery`. Extends {@link QueryObserverOptions} from - * `@tanstack/query-core` with the `preact-query`-specific `subscribed` option. + * The options shared by `useQuery` and `useSuspenseQuery`. Extends + * {@link QueryObserverOptions} from `@tanstack/query-core` with the + * `preact-query`-specific `subscribed` option. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. - * @template TQueryData - The type of the data actually held in the query cache — the input to `select` and - * `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. + * @template TQueryData - The type of the data actually held in the query cache + * — the input to `select` and `placeholderData`. Defaults to, and is usually + * the same as, `TQueryFnData`. * @template TQueryKey - The type of your `queryKey`. */ export interface UseBaseQueryOptions< @@ -56,21 +60,26 @@ export interface UseBaseQueryOptions< TQueryKey > { /** - * Set this to `false` to unsubscribe this observer from updates to the query cache. + * Set this to `false` to unsubscribe this observer from updates to the query + * cache. + * * @defaultValue true */ subscribed?: boolean } /** - * The options accepted by `usePrefetchQuery` — everything you can pass to `queryClient.query`, except `queryFn` - * is required unless a default query function has been defined. + * The options accepted by `usePrefetchQuery` — everything you can pass to + * `queryClient.query`, except `queryFn` is required unless a default query + * function has been defined. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. - * @template TQueryData - The type of the data actually held in the query cache — the input to `select` and - * `placeholderData`. Defaults to, and is usually the same as, `TQueryFnData`. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. + * @template TQueryData - The type of the data actually held in the query cache + * — the input to `select` and `placeholderData`. Defaults to, and is usually + * the same as, `TQueryFnData`. * @template TQueryKey - The type of your `queryKey`. */ export type UsePrefetchQueryOptions< @@ -84,8 +93,9 @@ export type UsePrefetchQueryOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — a prefetch always needs a query function to actually run, - * unless a default query function has been defined. + * `skipToken` is not allowed as a value here — a prefetch always needs a + * query function to actually run, unless a default query function has been + * defined. */ queryFn?: Exclude< QueryExecuteOptions< @@ -100,15 +110,20 @@ export type UsePrefetchQueryOptions< } /** - * The options accepted by `usePrefetchInfiniteQuery` — everything you can pass to `queryClient.infiniteQuery`, - * except `queryFn` is required unless a default query function has been defined. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by `usePrefetchInfiniteQuery` — everything you can pass + * to `queryClient.infiniteQuery`, except `queryFn` is required unless a default + * query function has been defined. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` (a single page) - * here, since a prefetch never reads `data` back out — this parameter only matters if you reuse these options - * elsewhere with `select` applied. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` (a single page) here, since a prefetch never reads `data` + * back out — this parameter only matters if you reuse these options elsewhere + * with `select` applied. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UsePrefetchInfiniteQueryOptions< TQueryFnData = unknown, @@ -127,8 +142,9 @@ export type UsePrefetchInfiniteQueryOptions< 'queryFn' > & { /** - * `skipToken` is not allowed as a value here — a prefetch always needs a query function to actually run, - * unless a default query function has been defined. + * `skipToken` is not allowed as a value here — a prefetch always needs a + * query function to actually run, unless a default query function has been + * defined. */ queryFn?: Exclude< InfiniteQueryExecuteOptions< @@ -143,17 +159,20 @@ export type UsePrefetchInfiniteQueryOptions< } /** - * {@link UseQueryOptions} with all type parameters set to `any`, useful when the specific types aren't - * relevant, e.g. when accepting options for any query in a helper function. + * {@link UseQueryOptions} with all type parameters set to `any`, useful when the + * specific types aren't relevant, e.g. when accepting options for any query in + * a helper function. */ export type AnyUseQueryOptions = UseQueryOptions /** - * The options accepted by `useQuery`. Same as {@link UseBaseQueryOptions}, minus `suspense` (which - * `preact-query` derives from which hook you call rather than exposing as an option). + * The options accepted by `useQuery`. Same as {@link UseBaseQueryOptions}, minus + * `suspense` (which `preact-query` derives from which hook you call rather than + * exposing as an option). + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. * @template TQueryKey - The type of your `queryKey`. */ export interface UseQueryOptions< @@ -167,8 +186,9 @@ export interface UseQueryOptions< > {} /** - * {@link UseSuspenseQueryOptions} with all type parameters set to `any`, useful when the specific types aren't - * relevant, e.g. when accepting options for any query in a helper function. + * {@link UseSuspenseQueryOptions} with all type parameters set to `any`, useful + * when the specific types aren't relevant, e.g. when accepting options for any + * query in a helper function. */ export type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions< any, @@ -177,13 +197,15 @@ export type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions< any > /** - * The options accepted by `useSuspenseQuery`. Same as {@link UseQueryOptions}, minus `enabled`, `throwOnError`, - * and `placeholderData` — Suspense hooks cannot render a "disabled" or "placeholder" state, so those options - * don't apply. + * The options accepted by `useSuspenseQuery`. Same as {@link UseQueryOptions}, + * minus `enabled`, `throwOnError`, and `placeholderData` — Suspense hooks + * cannot render a "disabled" or "placeholder" state, so those options don't + * apply. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs. Defaults to `TQueryFnData` when no - * `select` is used. + * @template TData - The type `data` ends up as after `select` runs. Defaults to + * `TQueryFnData` when no `select` is used. * @template TQueryKey - The type of your `queryKey`. */ export interface UseSuspenseQueryOptions< @@ -196,8 +218,9 @@ export interface UseSuspenseQueryOptions< 'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData' > { /** - * `skipToken` is not allowed here — Suspense hooks cannot render a "disabled" state, so a query function - * must always be provided, unless a default query function has been defined. + * `skipToken` is not allowed here — Suspense hooks cannot render a "disabled" + * state, so a query function must always be provided, unless a default query + * function has been defined. */ queryFn?: Exclude< UseQueryOptions['queryFn'], @@ -206,8 +229,9 @@ export interface UseSuspenseQueryOptions< } /** - * {@link UseInfiniteQueryOptions} with all type parameters set to `any`, useful when the specific types aren't - * relevant, e.g. when accepting options for any query in a helper function. + * {@link UseInfiniteQueryOptions} with all type parameters set to `any`, useful + * when the specific types aren't relevant, e.g. when accepting options for any + * query in a helper function. */ export type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions< any, @@ -217,15 +241,21 @@ export type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions< any > /** - * The options accepted by `useInfiniteQuery`. Extends {@link InfiniteQueryObserverOptions} from - * `@tanstack/query-core` with the `preact-query`-specific `subscribed` option, minus `suspense` (which - * `preact-query` derives from which hook you call rather than exposing as an option). - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by `useInfiniteQuery`. Extends + * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core` with the + * `preact-query`-specific `subscribed` option, minus `suspense` (which + * `preact-query` derives from which hook you call rather than exposing as an + * option). + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export interface UseInfiniteQueryOptions< TQueryFnData = unknown, @@ -244,28 +274,36 @@ export interface UseInfiniteQueryOptions< 'suspense' > { /** - * Set this to `false` to unsubscribe this observer from updates to the query cache. + * Set this to `false` to unsubscribe this observer from updates to the query + * cache. + * * @defaultValue true */ subscribed?: boolean } /** - * {@link UseSuspenseInfiniteQueryOptions} with all type parameters set to `any`, useful when the specific types - * aren't relevant, e.g. when accepting options for any query in a helper function. + * {@link UseSuspenseInfiniteQueryOptions} with all type parameters set to `any`, + * useful when the specific types aren't relevant, e.g. when accepting options + * for any query in a helper function. */ export type AnyUseSuspenseInfiniteQueryOptions = UseSuspenseInfiniteQueryOptions /** - * The options accepted by `useSuspenseInfiniteQuery`. Same as {@link UseInfiniteQueryOptions}, minus `enabled`, - * `throwOnError`, and `placeholderData` — Suspense hooks cannot render a "disabled" or "placeholder" state, so - * those options don't apply. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by `useSuspenseInfiniteQuery`. Same as + * {@link UseInfiniteQueryOptions}, minus `enabled`, `throwOnError`, and + * `placeholderData` — Suspense hooks cannot render a "disabled" or + * "placeholder" state, so those options don't apply. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export interface UseSuspenseInfiniteQueryOptions< TQueryFnData = unknown, @@ -278,8 +316,9 @@ export interface UseSuspenseInfiniteQueryOptions< 'queryFn' | 'enabled' | 'throwOnError' | 'placeholderData' > { /** - * `skipToken` is not allowed here — Suspense hooks cannot render a "disabled" state, so a query function - * must always be provided, unless a default query function has been defined. + * `skipToken` is not allowed here — Suspense hooks cannot render a "disabled" + * state, so a query function must always be provided, unless a default query + * function has been defined. */ queryFn?: Exclude< UseInfiniteQueryOptions< @@ -294,9 +333,11 @@ export interface UseSuspenseInfiniteQueryOptions< } /** - * The result of `useQuery` when `initialData` isn't set — `data` may be `undefined` while the query is - * `pending`. Re-exports {@link QueryObserverResult} from `@tanstack/query-core`. `useInfiniteQuery` returns - * {@link UseInfiniteQueryResult} instead. + * The result of `useQuery` when `initialData` isn't set — `data` may be + * `undefined` while the query is `pending`. Re-exports + * {@link QueryObserverResult} from `@tanstack/query-core`. `useInfiniteQuery` + * returns {@link UseInfiniteQueryResult} instead. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -307,6 +348,7 @@ export type UseBaseQueryResult< /** * The result of `useQuery`. Same as {@link UseBaseQueryResult}. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -316,8 +358,10 @@ export type UseQueryResult< > = UseBaseQueryResult /** - * The result of `useSuspenseQuery`. Same as {@link DefinedUseQueryResult}, minus `isPlaceholderData` — always - * `false` on that type, so this drops the dead field rather than an active state. + * The result of `useSuspenseQuery`. Same as {@link DefinedUseQueryResult}, minus + * `isPlaceholderData` — always `false` on that type, so this drops the dead + * field rather than an active state. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -330,9 +374,11 @@ export type UseSuspenseQueryResult< > /** - * The result of `useQuery` when `initialData` is set, or of `useSuspenseQuery` before the `isPlaceholderData` - * omission — `data` is never `undefined` (unless a `select` changes `TData` to include `undefined`). - * Re-exports {@link DefinedQueryObserverResult} from `@tanstack/query-core`. + * The result of `useQuery` when `initialData` is set, or of `useSuspenseQuery` + * before the `isPlaceholderData` omission — `data` is never `undefined` (unless + * a `select` changes `TData` to include `undefined`). Re-exports + * {@link DefinedQueryObserverResult} from `@tanstack/query-core`. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -342,8 +388,10 @@ export type DefinedUseQueryResult< > = DefinedQueryObserverResult /** - * The result of `useInfiniteQuery` when `initialData` isn't set — `data` may be `undefined` while the query is - * `pending`. Re-exports {@link InfiniteQueryObserverResult} from `@tanstack/query-core`. + * The result of `useInfiniteQuery` when `initialData` isn't set — `data` may be + * `undefined` while the query is `pending`. Re-exports + * {@link InfiniteQueryObserverResult} from `@tanstack/query-core`. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -353,9 +401,11 @@ export type UseInfiniteQueryResult< > = InfiniteQueryObserverResult /** - * The result of `useInfiniteQuery` when `initialData` is set — `data` is never `undefined` (unless a - * `select` changes `TData` to include `undefined`). Re-exports {@link DefinedInfiniteQueryObserverResult} - * from `@tanstack/query-core`. + * The result of `useInfiniteQuery` when `initialData` is set — `data` is never + * `undefined` (unless a `select` changes `TData` to include `undefined`). + * Re-exports {@link DefinedInfiniteQueryObserverResult} from + * `@tanstack/query-core`. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -365,8 +415,10 @@ export type DefinedUseInfiniteQueryResult< > = DefinedInfiniteQueryObserverResult /** - * The result of `useSuspenseInfiniteQuery`. Same as {@link DefinedUseInfiniteQueryResult}, minus - * `isPlaceholderData` — Suspense hooks never render placeholder data. + * The result of `useSuspenseInfiniteQuery`. Same as + * {@link DefinedUseInfiniteQueryResult}, minus `isPlaceholderData` — Suspense + * hooks never render placeholder data. + * * @template TData - The type `data` ends up as after `select` runs. * @template TError - The type of errors your `queryFn` may throw. */ @@ -379,18 +431,23 @@ export type UseSuspenseInfiniteQueryResult< > /** - * {@link UseMutationOptions} with all type parameters set to `any`, useful when the specific types aren't - * relevant, e.g. when accepting options for any mutation in a helper function. + * {@link UseMutationOptions} with all type parameters set to `any`, useful when + * the specific types aren't relevant, e.g. when accepting options for any + * mutation in a helper function. */ export type AnyUseMutationOptions = UseMutationOptions /** - * The options accepted by `useMutation`. Same as {@link MutationObserverOptions} from `@tanstack/query-core`, - * minus the internal `_defaulted` flag. + * The options accepted by `useMutation`. Same as + * {@link MutationObserverOptions} from `@tanstack/query-core`, minus the + * internal `_defaulted` flag. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export interface UseMutationOptions< TData = unknown, @@ -403,15 +460,18 @@ export interface UseMutationOptions< > {} /** - * The type of `mutate`, as returned by `useMutation`. Forwards the variables (and an optional per-call - * `onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced - * through the mutation result instead of being thrown by `mutate`, unless `throwOnError` makes `useMutation` - * rethrow them. + * The type of `mutate`, as returned by `useMutation`. Forwards the variables + * (and an optional per-call `onSuccess`/`onError`/`onSettled`) to the + * underlying `mutate` call. Fire-and-forget — errors are surfaced through the + * mutation result instead of being thrown by `mutate`, unless `throwOnError` + * makes `useMutation` rethrow them. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. * @template TVariables - The type of the variable passed to `mutate`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type UseMutateFunction< TData = unknown, @@ -425,13 +485,15 @@ export type UseMutateFunction< ) => void /** - * The type of `mutateAsync`, as returned by `useMutation`. Similar to {@link UseMutateFunction}, but returns a - * promise which can be awaited. + * The type of `mutateAsync`, as returned by `useMutation`. Similar to + * {@link UseMutateFunction}, but returns a promise which can be awaited. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. * @template TVariables - The type of the variable passed to `mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type UseMutateAsyncFunction< TData = unknown, @@ -441,13 +503,17 @@ export type UseMutateAsyncFunction< > = MutateFunction /** - * The result of `useMutation`. Same as {@link MutationObserverResult} from `@tanstack/query-core`, with - * `mutate` narrowed to the fire-and-forget {@link UseMutateFunction} signature, plus the added `mutateAsync`. + * The result of `useMutation`. Same as {@link MutationObserverResult} from + * `@tanstack/query-core`, with `mutate` narrowed to the fire-and-forget + * {@link UseMutateFunction} signature, plus the added `mutateAsync`. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type UseBaseMutationResult< TData = unknown, @@ -458,9 +524,7 @@ export type UseBaseMutationResult< MutationObserverResult, { mutate: UseMutateFunction } > & { - /** - * Similar to `mutate`, but returns a promise which can be awaited. - */ + /** Similar to `mutate`, but returns a promise which can be awaited. */ mutateAsync: UseMutateAsyncFunction< TData, TError, @@ -471,11 +535,14 @@ export type UseBaseMutationResult< /** * The result of `useMutation`. Same as {@link UseBaseMutationResult}. + * * @template TData - The type your mutation function resolves to. * @template TError - The type of errors your mutation function may throw. - * @template TVariables - The type of the variable passed to `mutate`/`mutateAsync`. - * @template TOnMutateResult - The type returned by `onMutate`, passed to `onSuccess`/`onError`/`onSettled` as - * their `onMutateResult` parameter — useful for optimistic-update rollback data. + * @template TVariables - The type of the variable passed to + * `mutate`/`mutateAsync`. + * @template TOnMutateResult - The type returned by `onMutate`, passed to + * `onSuccess`/`onError`/`onSettled` as their `onMutateResult` parameter — + * useful for optimistic-update rollback data. */ export type UseMutationResult< TData = unknown, diff --git a/packages/preact-query/src/useBaseQuery.ts b/packages/preact-query/src/useBaseQuery.ts index c4a0650ea63..14c0695b1dd 100644 --- a/packages/preact-query/src/useBaseQuery.ts +++ b/packages/preact-query/src/useBaseQuery.ts @@ -24,17 +24,19 @@ import type { } from '@tanstack/query-core' /** - * Base implementation shared by `useQuery`, `useInfiniteQuery`, `useSuspenseQuery`, and - * `useSuspenseInfiniteQuery`. + * Base implementation shared by `useQuery`, `useInfiniteQuery`, + * `useSuspenseQuery`, and `useSuspenseInfiniteQuery`. + * * @param options - The options passed to the calling hook. * @param Observer - The observer class from query-core (`QueryObserver` or - * `InfiniteQueryObserver`). - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest - * context will be used. - * @returns The query result, tracking which properties are read unless `notifyOnChangeProps` is - * set. - * @throws {Error} If `options` is not an object (outside production), or the query error when it should be - * thrown to the nearest error boundary (see `throwOnError`). While suspending, it throws a promise instead. + * `InfiniteQueryObserver`). + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The query result, tracking which properties are read unless + * `notifyOnChangeProps` is set. + * @throws {Error} If `options` is not an object (outside production), or the + * query error when it should be thrown to the nearest error boundary (see + * `throwOnError`). While suspending, it throws a promise instead. */ export function useBaseQuery< TQueryFnData, diff --git a/packages/preact-query/src/useInfiniteQuery.ts b/packages/preact-query/src/useInfiniteQuery.ts index f4b352c8a16..32d8159b25b 100644 --- a/packages/preact-query/src/useInfiniteQuery.ts +++ b/packages/preact-query/src/useInfiniteQuery.ts @@ -19,46 +19,55 @@ import type { } from './types' /** - * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. + * The options for `useInfiniteQuery` are identical to `useQuery`, with the + * addition of `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, + * and `maxPages`. * * This overload is selected when `initialData` is set. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`, with `initialData` set. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and - * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage && !isFetching`. - * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage && !isFetching`. * @example - * ```tsx - * import { useInfiniteQuery } from '@tanstack/preact-query' - * - * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * }) + * ```tsx + * import { useInfiniteQuery } from '@tanstack/preact-query' * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => page.projects.map((p) =>
  • {p.name}
  • ))} - *
- *
- * ) - * } - * ``` + * function Projects() { + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, + * }) + * + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) + * } + * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`, with `initialData` set. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and + * `data.pageParams` are also added, as long as a `select` doesn't change + * `TData` away from its default `InfiniteData` shape. + * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. */ export function useInfiniteQuery< TQueryFnData, @@ -78,110 +87,118 @@ export function useInfiniteQuery< ): DefinedUseInfiniteQueryResult /** - * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to `useInfiniteQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and - * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage && !isFetching`. - * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. + * The options for `useInfiniteQuery` are identical to `useQuery`, with the + * addition of `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, + * and `maxPages`. + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage && !isFetching`. * @example - * Fetching the next page from a "Load More" button click: - * ```tsx - * import { useInfiniteQuery } from '@tanstack/preact-query' + * Fetching the next page from a "Load More" button click: + * ```tsx + * import { useInfiniteQuery } from '@tanstack/preact-query' * - * function Projects() { + * function Projects() { * const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } = - * useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * }) + * useInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * }) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - * <> - *
    - * {data.pages.map((page) => - * page.projects.map((project) =>
  • {project.name}
  • ), - * )} - *
- * - * + * <> + *
    + * {data.pages.map((page) => + * page.projects.map((project) =>
  • {project.name}
  • ), + * )} + *
+ * + * * ) - * } - * ``` + * } + * ``` + * * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a - * sentinel element after the list: - * ```tsx - * import { useInfiniteQuery } from '@tanstack/preact-query' - * import { useEffect, useRef } from 'preact/hooks' + * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a + * sentinel element after the list: + * ```tsx + * import { useInfiniteQuery } from '@tanstack/preact-query' + * import { useEffect, useRef } from 'preact/hooks' * - * function Projects() { + * function Projects() { * const { - * data, - * isPending, - * isError, - * error, - * fetchNextPage, - * hasNextPage, - * isFetching, - * isFetchingNextPage, + * data, + * isPending, + * isError, + * error, + * fetchNextPage, + * hasNextPage, + * isFetching, + * isFetchingNextPage, * } = useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * * const sentinelRef = useRef(null) * * useEffect(() => { - * const sentinel = sentinelRef.current - * if (sentinel == null || !hasNextPage || isFetching) return + * const sentinel = sentinelRef.current + * if (sentinel == null || !hasNextPage || isFetching) return * - * const observer = new IntersectionObserver(([entry]) => { - * if (entry?.isIntersecting) fetchNextPage() - * }) - * observer.observe(sentinel) + * const observer = new IntersectionObserver(([entry]) => { + * if (entry?.isIntersecting) fetchNextPage() + * }) + * observer.observe(sentinel) * - * return () => observer.disconnect() + * return () => observer.disconnect() * }, [hasNextPage, isFetching, fetchNextPage]) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - * <> - *
    - * {data.pages.map((page) => - * page.projects.map((project) =>
  • {project.name}
  • ), - * )} - *
- *
{isFetchingNextPage ? 'Loading more...' : null}
- * + * <> + *
    + * {data.pages.map((page) => + * page.projects.map((project) =>
  • {project.name}
  • ), + * )} + *
+ *
{isFetchingNextPage ? 'Loading more...' : null}
+ * * ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and + * `data.pageParams` are also added, as long as a `select` doesn't change + * `TData` away from its default `InfiniteData` shape. + * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. */ export function useInfiniteQuery< TQueryFnData, @@ -201,126 +218,124 @@ export function useInfiniteQuery< ): UseInfiniteQueryResult /** - * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. - * @param options - The {@link UseInfiniteQueryOptions} to use — everything you can pass to `useInfiniteQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and - * `data.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage && !isFetching`. - * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. + * The options for `useInfiniteQuery` are identical to `useQuery`, with the + * addition of `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, + * and `maxPages`. + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage && !isFetching`. * @example - * Fetching the next page from a "Load More" button click: - * ```tsx - * import { useInfiniteQuery } from '@tanstack/preact-query' + * Fetching the next page from a "Load More" button click: + * ```tsx + * import { useInfiniteQuery } from '@tanstack/preact-query' * - * function Projects() { + * function Projects() { * const { data, isPending, isError, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } = - * useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * }) + * useInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * }) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - * <> - *
    - * {data.pages.map((page) => - * page.projects.map((project) =>
  • {project.name}
  • ), - * )} - *
- * - * + * <> + *
    + * {data.pages.map((page) => + * page.projects.map((project) =>
  • {project.name}
  • ), + * )} + *
+ * + * * ) - * } - * ``` + * } + * ``` + * * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a - * sentinel element after the list: - * ```tsx - * import { useInfiniteQuery } from '@tanstack/preact-query' - * import { useEffect, useRef } from 'preact/hooks' + * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a + * sentinel element after the list: + * ```tsx + * import { useInfiniteQuery } from '@tanstack/preact-query' + * import { useEffect, useRef } from 'preact/hooks' * - * function Projects() { + * function Projects() { * const { - * data, - * isPending, - * isError, - * error, - * fetchNextPage, - * hasNextPage, - * isFetching, - * isFetchingNextPage, + * data, + * isPending, + * isError, + * error, + * fetchNextPage, + * hasNextPage, + * isFetching, + * isFetchingNextPage, * } = useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * * const sentinelRef = useRef(null) * * useEffect(() => { - * const sentinel = sentinelRef.current - * if (sentinel == null || !hasNextPage || isFetching) return + * const sentinel = sentinelRef.current + * if (sentinel == null || !hasNextPage || isFetching) return * - * const observer = new IntersectionObserver(([entry]) => { - * if (entry?.isIntersecting) fetchNextPage() - * }) - * observer.observe(sentinel) + * const observer = new IntersectionObserver(([entry]) => { + * if (entry?.isIntersecting) fetchNextPage() + * }) + * observer.observe(sentinel) * - * return () => observer.disconnect() + * return () => observer.disconnect() * }, [hasNextPage, isFetching, fetchNextPage]) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - * <> - *
    - * {data.pages.map((page) => - * page.projects.map((project) =>
  • {project.name}
  • ), - * )} - *
- *
{isFetchingNextPage ? 'Loading more...' : null}
- * + * <> + *
    + * {data.pages.map((page) => + * page.projects.map((project) =>
  • {project.name}
  • ), + * )} + *
+ *
{isFetchingNextPage ? 'Loading more...' : null}
+ * * ) - * } - * ``` + * } + * ``` + * * @example - * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` - * instead of setting `enabled: false`: - * ```tsx - * import { skipToken, useInfiniteQuery } from '@tanstack/preact-query' + * A query that's disabled, type safe, until `postId` is set — pass `skipToken` as `queryFn` + * instead of setting `enabled: false`: + * ```tsx + * import { skipToken, useInfiniteQuery } from '@tanstack/preact-query' * - * function Comments({ postId }: { postId: string | undefined }) { + * function Comments({ postId }: { postId: string | undefined }) { * // Use `isLoading`, not `isPending`, so the loading state doesn't show while the query is disabled. * const { data, isLoading, isError, error } = useInfiniteQuery({ - * queryKey: ['post', postId, 'comments'], - * queryFn: - * postId != null - * ? ({ pageParam }) => fetchComments(postId, pageParam) - * : skipToken, - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, + * queryKey: ['post', postId, 'comments'], + * queryFn: + * postId != null + * ? ({ pageParam }) => fetchComments(postId, pageParam) + * : skipToken, + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, * }) * * if (postId == null) return 'Select a post' @@ -328,12 +343,23 @@ export function useInfiniteQuery< * if (isError) return Error: {error.message} * * return ( - *
    - * {data?.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} - *
+ *
    + * {data?.pages.map((page) => page.comments.map((c) =>
  • {c.text}
  • ))} + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UseInfiniteQueryOptions} to use — everything you + * can pass to `useInfiniteQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.pages` and + * `data.pageParams` are also added, as long as a `select` doesn't change + * `TData` away from its default `InfiniteData` shape. + * @see {@link infiniteQueryOptions} to share these options between `useInfiniteQuery` and imperative APIs like `queryClient.infiniteQuery`. */ export function useInfiniteQuery< TQueryFnData, diff --git a/packages/preact-query/src/useIsFetching.ts b/packages/preact-query/src/useIsFetching.ts index 3cbf2e6a856..ff337c9169f 100644 --- a/packages/preact-query/src/useIsFetching.ts +++ b/packages/preact-query/src/useIsFetching.ts @@ -6,37 +6,41 @@ import { useSyncExternalStore } from './utils' import type { QueryClient, QueryFilters } from '@tanstack/query-core' /** - * The `useIsFetching` hook returns the `number` of the queries that your application is loading or fetching in - * the background (useful for app-wide loading indicators). - * @param filters - The {@link QueryFilters} to narrow down the matched queries. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns Will be the `number` of the queries that your application is currently loading or fetching in the - * background. + * The `useIsFetching` hook returns the `number` of the queries that your + * application is loading or fetching in the background (useful for app-wide + * loading indicators). + * * @example - * ```tsx - * import { useIsFetching } from '@tanstack/preact-query' + * ```tsx + * import { useIsFetching } from '@tanstack/preact-query' + * + * function PostsFetchingIndicator() { + * // How many queries matching the posts prefix are fetching? + * const isFetchingPosts = useIsFetching({ queryKey: ['posts'] }) * - * function PostsFetchingIndicator() { - * // How many queries matching the posts prefix are fetching? - * const isFetchingPosts = useIsFetching({ queryKey: ['posts'] }) + * return isFetchingPosts ? Refreshing posts... : null + * } + * ``` * - * return isFetchingPosts ? Refreshing posts... : null - * } - * ``` * @example - * A global loading indicator for any query fetching in the background, not just the ones on screen: - * ```tsx - * import { useIsFetching } from '@tanstack/preact-query' + * A global loading indicator for any query fetching in the background, not just the ones on screen: + * ```tsx + * import { useIsFetching } from '@tanstack/preact-query' * - * function GlobalLoadingIndicator() { + * function GlobalLoadingIndicator() { * const isFetching = useIsFetching() * * return isFetching ? ( - *
Queries are fetching in the background...
+ *
Queries are fetching in the background...
* ) : null - * } - * ``` + * } + * ``` + * + * @param filters - The {@link QueryFilters} to narrow down the matched queries. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns Will be the `number` of the queries that your application is + * currently loading or fetching in the background. */ export function useIsFetching( filters?: QueryFilters, diff --git a/packages/preact-query/src/useMutation.ts b/packages/preact-query/src/useMutation.ts index 740485c4702..2c9b873637f 100644 --- a/packages/preact-query/src/useMutation.ts +++ b/packages/preact-query/src/useMutation.ts @@ -18,172 +18,183 @@ import type { DefaultError, QueryClient } from '@tanstack/query-core' // HOOK /** - * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. - * `useMutation` is the hook for that. - * @param options - The {@link UseMutationOptions} to use — everything you can pass to `useMutation`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second - * argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared - * mutation definition. Hook-level callbacks (passed to `options`) fire for every mutation; per-call callbacks - * fire only for the latest call you've made, and only while the component is still mounted — unmounting before - * the mutation settles removes the subscription and prevents them from firing. - * @throws {Error} The mutation error, when `throwOnError` is `true` or returns `true` for it, so that it is - * thrown to the nearest error boundary. - * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites, or to look - * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). + * Unlike queries, mutations are typically used to create/update/delete data or + * perform server side-effects. `useMutation` is the hook for that. + * * @example - * ```tsx - * import { useMutation, useQueryClient } from '@tanstack/preact-query' + * ```tsx + * import { useMutation, useQueryClient } from '@tanstack/preact-query' * - * function AddTodo() { - * const queryClient = useQueryClient() + * function AddTodo() { + * const queryClient = useQueryClient() * - * const addMutation = useMutation({ - * mutationFn: addTodo, - * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), - * }) + * const addMutation = useMutation({ + * mutationFn: addTodo, + * onSuccess: () => + * queryClient.invalidateQueries({ queryKey: ['todos'] }), + * }) + * + * return ( + * + * ) + * } + * ``` * - * return ( - * - * ) - * } - * ``` * @example - * Rendering the mutation's own state, rather than just firing it off: - * ```tsx - * import { useMutation, useQueryClient } from '@tanstack/preact-query' + * Rendering the mutation's own state, rather than just firing it off: + * ```tsx + * import { useMutation, useQueryClient } from '@tanstack/preact-query' * - * function AddTodo() { + * function AddTodo() { * const queryClient = useQueryClient() * * const addMutation = useMutation({ - * mutationFn: addTodo, - * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), * }) * * return ( - *
- * {addMutation.isPending ? ( - * 'Adding todo...' - * ) : ( - * <> - * {addMutation.isError ? ( - *
An error occurred: {addMutation.error.message}
- * ) : null} - * - * - * )} - *
+ *
+ * {addMutation.isPending ? ( + * 'Adding todo...' + * ) : ( + * <> + * {addMutation.isError ? ( + *
An error occurred: {addMutation.error.message}
+ * ) : null} + * + * + * )} + *
* ) - * } - * ``` + * } + * ``` + * * @example - * Optimistic update via `onMutate`, rolling back on `onError`: - * ```tsx - * import { useMutation, useQueryClient } from '@tanstack/preact-query' + * Optimistic update via `onMutate`, rolling back on `onError`: + * ```tsx + * import { useMutation, useQueryClient } from '@tanstack/preact-query' * - * function AddTodo() { + * function AddTodo() { * const queryClient = useQueryClient() * * const addMutation = useMutation({ - * mutationFn: addTodo, - * onMutate: async (newTodo) => { - * await queryClient.cancelQueries({ queryKey: ['todos'] }) - * const previousTodos = queryClient.getQueryData>(['todos']) - * - * queryClient.setQueryData>(['todos'], (old) => [ - * ...(old ?? []), - * newTodo, - * ]) - * - * // Passed to `onError` as `onMutateResult` if the mutation fails. - * return { previousTodos } - * }, - * onError: (_err, _newTodo, onMutateResult) => { - * queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) - * }, - * onSettled: () => { - * queryClient.invalidateQueries({ queryKey: ['todos'] }) - * }, + * mutationFn: addTodo, + * onMutate: async (newTodo) => { + * await queryClient.cancelQueries({ queryKey: ['todos'] }) + * const previousTodos = queryClient.getQueryData>(['todos']) + * + * queryClient.setQueryData>(['todos'], (old) => [ + * ...(old ?? []), + * newTodo, + * ]) + * + * // Passed to `onError` as `onMutateResult` if the mutation fails. + * return { previousTodos } + * }, + * onError: (_err, _newTodo, onMutateResult) => { + * queryClient.setQueryData(['todos'], onMutateResult?.previousTodos) + * }, + * onSettled: () => { + * queryClient.invalidateQueries({ queryKey: ['todos'] }) + * }, * }) * * return ( - * + * * ) - * } - * ``` + * } + * ``` + * * @example - * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a - * promise per call instead, so you can wait for all of them when they succeed: - * ```tsx - * import { useMutation, useQueryClient } from '@tanstack/preact-query' + * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a + * promise per call instead, so you can wait for all of them when they succeed: + * ```tsx + * import { useMutation, useQueryClient } from '@tanstack/preact-query' * - * function AddTodos() { + * function AddTodos() { * const queryClient = useQueryClient() * * const addMutation = useMutation({ - * mutationFn: addTodo, - * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), * }) * * async function handleAddAll(todos: Array) { - * try { - * await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo))) - * } catch (error) { - * console.error('Failed to add todos:', error) - * } + * try { + * await Promise.all(todos.map((todo) => addMutation.mutateAsync(todo))) + * } catch (error) { + * console.error('Failed to add todos:', error) + * } * } * * return ( - * + * * ) - * } - * ``` + * } + * ``` + * * @example - * If some of the mutations above can fail independently of the others, and you want to know which ones - * did — rather than losing that information the moment the first one rejects — swap `Promise.all` for - * `Promise.allSettled`: - * ```tsx - * import { useMutation, useQueryClient } from '@tanstack/preact-query' + * If some of the mutations above can fail independently of the others, and you want to know which ones + * did — rather than losing that information the moment the first one rejects — swap `Promise.all` for + * `Promise.allSettled`: + * ```tsx + * import { useMutation, useQueryClient } from '@tanstack/preact-query' * - * function AddTodos() { + * function AddTodos() { * const queryClient = useQueryClient() * * const addMutation = useMutation({ - * mutationFn: addTodo, - * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), + * mutationFn: addTodo, + * onSuccess: () => queryClient.invalidateQueries({ queryKey: ['todos'] }), * }) * * async function handleAddAll(todos: Array) { - * const addResults = await Promise.allSettled( - * todos.map((todo) => addMutation.mutateAsync(todo)), - * ) + * const addResults = await Promise.allSettled( + * todos.map((todo) => addMutation.mutateAsync(todo)), + * ) * - * addResults.forEach((addResult, index) => { - * if (addResult.status === 'rejected') { - * console.error(`Failed to add "${todos[index]}":`, addResult.reason) - * } - * }) + * addResults.forEach((addResult, index) => { + * if (addResult.status === 'rejected') { + * console.error(`Failed to add "${todos[index]}":`, addResult.reason) + * } + * }) * } * * return ( - * + * * ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UseMutationOptions} to use — everything you can + * pass to `useMutation`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns `mutate`/`mutateAsync` also accept per-call + * `onSuccess`/`onError`/`onSettled` callbacks as a second argument, useful + * for triggering call-site side effects (e.g. navigation) without coupling + * them to the shared mutation definition. Hook-level callbacks (passed to + * `options`) fire for every mutation; per-call callbacks fire only for the + * latest call you've made, and only while the component is still mounted — + * unmounting before the mutation settles removes the subscription and + * prevents them from firing. + * @throws {Error} The mutation error, when `throwOnError` is `true` or returns + * `true` for it, so that it is thrown to the nearest error boundary. + * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites, or to look + * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). */ export function useMutation< TData = unknown, diff --git a/packages/preact-query/src/useMutationState.ts b/packages/preact-query/src/useMutationState.ts index a76471c8ed7..314103ab270 100644 --- a/packages/preact-query/src/useMutationState.ts +++ b/packages/preact-query/src/useMutationState.ts @@ -12,23 +12,28 @@ import type { } from '@tanstack/query-core' /** - * The `useIsMutating` hook returns the `number` of mutations that your application currently has `pending` - * (useful for app-wide loading indicators). - * @param filters - The {@link MutationFilters} to narrow down the matched mutations. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns Will be the `number` of the mutations that your application currently has `pending`. + * The `useIsMutating` hook returns the `number` of mutations that your + * application currently has `pending` (useful for app-wide loading + * indicators). + * * @example - * ```tsx - * import { useIsMutating } from '@tanstack/preact-query' + * ```tsx + * import { useIsMutating } from '@tanstack/preact-query' + * + * function PostsMutatingIndicator() { + * // How many mutations matching the posts prefix are in progress? + * const isMutatingPosts = useIsMutating({ mutationKey: ['posts'] }) * - * function PostsMutatingIndicator() { - * // How many mutations matching the posts prefix are in progress? - * const isMutatingPosts = useIsMutating({ mutationKey: ['posts'] }) + * return isMutatingPosts ? Saving posts... : null + * } + * ``` * - * return isMutatingPosts ? Saving posts... : null - * } - * ``` + * @param filters - The {@link MutationFilters} to narrow down the matched + * mutations. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns Will be the `number` of the mutations that your application + * currently has `pending`. */ export function useIsMutating( filters?: MutationFilters, @@ -62,9 +67,10 @@ type MutationStateOptions< } /** - * Creates snapshot getters that share equal selected results across renders. - * A new getter is created on each render. Each getter caches its snapshot until the matching mutations - * or their states change. + * Creates snapshot getters that share equal selected results across renders. A + * new getter is created on each render. Each getter caches its snapshot until + * the matching mutations or their states change. + * * @returns A factory for snapshot getters with a shared result cache. */ function createSnapshotFactory< @@ -112,73 +118,78 @@ function createSnapshotFactory< } /** - * `useMutationState` is a hook that gives you access to all mutations in the `MutationCache`. You can pass - * `filters` ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the mutation - * state. - * @param options - The `filters` to narrow down matched mutations, and an optional `select` to transform the - * mutation state. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns Will be an Array of whatever `select` returns for each matching mutation. + * `useMutationState` is a hook that gives you access to all mutations in the + * `MutationCache`. You can pass `filters` ({@link MutationFilters}) to narrow + * down your mutations, and `select` to transform the mutation state. + * * @example - * Get all variables of all running mutations: - * ```tsx - * import { useMutationState } from '@tanstack/preact-query' + * Get all variables of all running mutations: + * ```tsx + * import { useMutationState } from '@tanstack/preact-query' * - * function PendingPosts() { + * function PendingPosts() { * const pendingVariables = useMutationState({ - * filters: { status: 'pending' }, - * select: (mutation) => mutation.state.variables, + * filters: { status: 'pending' }, + * select: (mutation) => mutation.state.variables, * }) * * return <>{pendingVariables.length} posts saving... - * } - * ``` + * } + * ``` + * * @example - * Get all data for specific mutations via the `mutationKey`: - * ```tsx - * import { useMutation, useMutationState } from '@tanstack/preact-query' + * Get all data for specific mutations via the `mutationKey`: + * ```tsx + * import { useMutation, useMutationState } from '@tanstack/preact-query' * - * const mutationKey = ['posts'] + * const mutationKey = ['posts'] * - * function Posts() { + * function Posts() { * // Some mutation that we want to get the state for * const mutation = useMutation({ - * mutationKey, - * mutationFn: createPosts, + * mutationKey, + * mutationFn: createPosts, * }) * * const savedPosts = useMutationState({ - * // this mutation key needs to match the mutation key of the given mutation (see above) - * filters: { mutationKey, status: 'success' }, - * select: (mutation) => mutation.state.data, + * // this mutation key needs to match the mutation key of the given mutation (see above) + * filters: { mutationKey, status: 'success' }, + * select: (mutation) => mutation.state.data, * }) * * return ( - * + * * ) - * } - * ``` + * } + * ``` + * * @example - * Access the latest successful mutation data via the `mutationKey`. Each invocation of `mutate` adds a new - * entry to the mutation cache for `gcTime` milliseconds — with the `status: 'success'` filter below, check the - * last item that `useMutationState` returns to get the latest successful invocation: - * ```tsx - * import { useMutationState } from '@tanstack/preact-query' + * Access the latest successful mutation data via the `mutationKey`. Each invocation of `mutate` adds a new + * entry to the mutation cache for `gcTime` milliseconds — with the `status: 'success'` filter below, check the + * last item that `useMutationState` returns to get the latest successful invocation: + * ```tsx + * import { useMutationState } from '@tanstack/preact-query' * - * function LatestPost() { + * function LatestPost() { * const savedPosts = useMutationState({ - * filters: { mutationKey: ['posts'], status: 'success' }, - * select: (mutation) => mutation.state.data, + * filters: { mutationKey: ['posts'], status: 'success' }, + * select: (mutation) => mutation.state.data, * }) * * const latestSavedPost = savedPosts[savedPosts.length - 1] * * return <>{latestSavedPost ? 'Saved' : 'Nothing saved yet'} - * } - * ``` + * } + * ``` + * + * @param options - The `filters` to narrow down matched mutations, and an + * optional `select` to transform the mutation state. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns Will be an Array of whatever `select` returns for each matching + * mutation. */ export function useMutationState< TResult = MutationState, diff --git a/packages/preact-query/src/usePrefetchInfiniteQuery.tsx b/packages/preact-query/src/usePrefetchInfiniteQuery.tsx index f7e6b8381e2..5b32a859244 100644 --- a/packages/preact-query/src/usePrefetchInfiniteQuery.tsx +++ b/packages/preact-query/src/usePrefetchInfiniteQuery.tsx @@ -5,45 +5,56 @@ import type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core' import type { UsePrefetchInfiniteQueryOptions } from './types' /** - * `usePrefetchInfiniteQuery` does not return anything, it should be used just to fire a prefetch during render, - * before a suspense boundary that wraps a component that uses `useSuspenseInfiniteQuery`. You can pass - * everything to `usePrefetchInfiniteQuery` that you can pass to `queryClient.infiniteQuery`, though - * `queryKey`, `initialPageParam`, and `getNextPageParam` are always required, and `queryFn` is required unless - * a default query function has been defined. + * `usePrefetchInfiniteQuery` does not return anything, it should be used just + * to fire a prefetch during render, before a suspense boundary that wraps a + * component that uses `useSuspenseInfiniteQuery`. You can pass everything to + * `usePrefetchInfiniteQuery` that you can pass to `queryClient.infiniteQuery`, + * though `queryKey`, `initialPageParam`, and `getNextPageParam` are always + * required, and `queryFn` is required unless a default query function has been + * defined. * - * `getNextPageParam` receives both the last page of the infinite list of data and the full array of all pages, - * as well as pageParam information, and should return a single variable that will be passed to your query - * function as `context.pageParam`. Return `undefined` or `null` to indicate there is no next page available. + * `getNextPageParam` receives both the last page of the infinite list of data + * and the full array of all pages, as well as pageParam information, and should + * return a single variable that will be passed to your query function as + * `context.pageParam`. Return `undefined` or `null` to indicate there is no + * next page available. + * + * The prefetch is skipped if the query already has any cached state — including + * a `pending`/`error` state left over from a previous attempt — so calling this + * on every render is cheap and won't refetch data that's already there or + * already in flight. * - * The prefetch is skipped if the query already has any cached state — including a `pending`/`error` state left - * over from a previous attempt — so calling this on every render is cheap and won't refetch data that's - * already there or already in flight. - * @param options - The {@link UsePrefetchInfiniteQueryOptions} to use — everything you can pass to `queryClient.infiniteQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. * @example - * ```tsx - * import { Suspense } from 'preact/compat' - * import { infiniteQueryOptions, usePrefetchInfiniteQuery } from '@tanstack/preact-query' + * ```tsx + * import { Suspense } from 'preact/compat' + * import { + * infiniteQueryOptions, + * usePrefetchInfiniteQuery, + * } from '@tanstack/preact-query' + * + * const projectsOptions = infiniteQueryOptions({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * }) * - * const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * }) + * function App() { + * // Fire the prefetch during render, before the suspense boundary below. + * usePrefetchInfiniteQuery(projectsOptions) * - * function App() { - * // Fire the prefetch during render, before the suspense boundary below. - * usePrefetchInfiniteQuery(projectsOptions) + * return ( + * Loading projects...}> + * + * + * ) + * } + * ``` * - * return ( - * Loading projects...}> - * - * - * ) - * } - * ``` + * @param options - The {@link UsePrefetchInfiniteQueryOptions} to use — + * everything you can pass to `queryClient.infiniteQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. */ export function usePrefetchInfiniteQuery< TQueryFnData = unknown, diff --git a/packages/preact-query/src/usePrefetchQuery.tsx b/packages/preact-query/src/usePrefetchQuery.tsx index b79c5178899..ae2910d7a5a 100644 --- a/packages/preact-query/src/usePrefetchQuery.tsx +++ b/packages/preact-query/src/usePrefetchQuery.tsx @@ -5,36 +5,42 @@ import type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core' import type { UsePrefetchQueryOptions } from './types' /** - * `usePrefetchQuery` does not return anything, it should be used just to fire a prefetch during render, before - * a suspense boundary that wraps a component that uses `useSuspenseQuery`. You can pass everything to - * `usePrefetchQuery` that you can pass to `queryClient.query`, though `queryKey` is always required, and - * `queryFn` is required unless a default query function has been defined. + * `usePrefetchQuery` does not return anything, it should be used just to fire a + * prefetch during render, before a suspense boundary that wraps a component + * that uses `useSuspenseQuery`. You can pass everything to `usePrefetchQuery` + * that you can pass to `queryClient.query`, though `queryKey` is always + * required, and `queryFn` is required unless a default query function has been + * defined. + * + * The prefetch is skipped if the query already has any cached state — including + * a `pending`/`error` state left over from a previous attempt — so calling this + * on every render is cheap and won't refetch data that's already there or + * already in flight. * - * The prefetch is skipped if the query already has any cached state — including a `pending`/`error` state left - * over from a previous attempt — so calling this on every render is cheap and won't refetch data that's - * already there or already in flight. - * @param options - The {@link UsePrefetchQueryOptions} to use — everything you can pass to `queryClient.query`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. * @example - * ```tsx - * import { Suspense } from 'preact/compat' - * import { usePrefetchQuery } from '@tanstack/preact-query' + * ```tsx + * import { Suspense } from 'preact/compat' + * import { usePrefetchQuery } from '@tanstack/preact-query' + * + * function App() { + * // Fire the prefetch during render, before the suspense boundary below. + * usePrefetchQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) * - * function App() { - * // Fire the prefetch during render, before the suspense boundary below. - * usePrefetchQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) + * return ( + * Loading posts...}> + * + * + * ) + * } + * ``` * - * return ( - * Loading posts...}> - * - * - * ) - * } - * ``` + * @param options - The {@link UsePrefetchQueryOptions} to use — everything you + * can pass to `queryClient.query`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. */ export function usePrefetchQuery< TQueryFnData = unknown, diff --git a/packages/preact-query/src/useQueries.ts b/packages/preact-query/src/useQueries.ts index e6b4237c9b4..cbf6b5e3a20 100644 --- a/packages/preact-query/src/useQueries.ts +++ b/packages/preact-query/src/useQueries.ts @@ -142,19 +142,22 @@ type GetUseQueryResult = UseQueryResult /** - * The `queries` array accepted by `useQueries`. Recursively unwraps each tuple element so every entry's - * `queryFn`/`select`/`throwOnError` are inferred individually, up to 20 elements — past that, a tuple falls - * back to a single homogeneous options type. + * The `queries` array accepted by `useQueries`. Recursively unwraps each tuple + * element so every entry's `queryFn`/`select`/`throwOnError` are inferred + * individually, up to 20 elements — past that, a tuple falls back to a single + * homogeneous options type. + * + * An opaque array (e.g. `unknown[]`) is returned as-is; a non-tuple array whose + * element type structurally matches a query options object is mapped + * per-element instead, still inferring each entry individually; any other + * non-tuple array — one whose element type doesn't match the expected options + * shape — falls back to that same homogeneous options type too. * - * An opaque array (e.g. `unknown[]`) is returned as-is; a non-tuple array whose element type structurally - * matches a query options object is mapped per-element instead, still inferring each entry individually; any - * other non-tuple array — one whose element type doesn't match the expected options shape — falls back to - * that same homogeneous options type too. * @template T - The type of the `queries` array as written at the call site. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant - * to be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type QueriesOptions< T extends Array, @@ -196,15 +199,18 @@ export type QueriesOptions< Array /** - * The result type returned by `useQueries`, when no `combine` is provided. Mirrors {@link QueriesOptions}: each - * tuple element's result type is inferred individually, up to 20 elements. A non-tuple array is mapped - * per-element instead, still inferring each entry individually; only past 20 elements does this fall back to a - * single homogeneous {@link UseQueryResult} type. - * @template T - The type of the `queries` array, as inferred by {@link QueriesOptions}. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant - * to be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * The result type returned by `useQueries`, when no `combine` is provided. + * Mirrors {@link QueriesOptions}: each tuple element's result type is inferred + * individually, up to 20 elements. A non-tuple array is mapped per-element + * instead, still inferring each entry individually; only past 20 elements does + * this fall back to a single homogeneous {@link UseQueryResult} type. + * + * @template T - The type of the `queries` array, as inferred by + * {@link QueriesOptions}. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type QueriesResults< T extends Array, @@ -227,79 +233,89 @@ export type QueriesResults< /** * The `useQueries` hook can be used to fetch a variable number of queries. * - * The `queries` key accepts an array with query option objects mostly identical to `useQuery` — see the - * `queries` parameter below for the differences. A custom `QueryClient` is supplied once, as `useQueries`' own - * top-level second argument, rather than per query. + * The `queries` key accepts an array with query option objects mostly identical + * to `useQuery` — see the `queries` parameter below for the differences. A + * custom `QueryClient` is supplied once, as `useQueries`' own top-level second + * argument, rather than per query. * - * Having the same query key more than once in the array of query objects may cause some data to be shared - * between queries. To avoid this, consider de-duplicating the queries and map the results back to the desired + * Having the same query key more than once in the array of query objects may + * cause some data to be shared between queries. To avoid this, consider + * de-duplicating the queries and map the results back to the desired * structure. * - * The `combine` option can be used to combine the results of the queries into a single value. The result will - * be structurally shared to be as referentially stable as possible. - * @param options - The `queries` array to run, and the optional `combine` and `subscribed` options. - * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, the one from the nearest context - * will be used. - * @returns The combined result. Without `combine`, this is an array with all the query results, in the same - * order as the input. When `combine` is provided, this is the value returned by `combine` instead. - * @throws {Error} The error of the first query that should be thrown to the nearest error boundary (see - * `throwOnError`). While suspending, it throws a promise instead. + * The `combine` option can be used to combine the results of the queries into a + * single value. The result will be structurally shared to be as referentially + * stable as possible. + * * @example - * ```tsx - * import { useQueries } from '@tanstack/preact-query' + * ```tsx + * import { useQueries } from '@tanstack/preact-query' * - * function Posts({ ids }: { ids: Array }) { - * const postQueries = useQueries({ - * queries: ids.map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * staleTime: Infinity, - * })), - * }) + * function Posts({ ids }: { ids: Array }) { + * const postQueries = useQueries({ + * queries: ids.map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * staleTime: Infinity, + * })), + * }) + * + * return ( + *
    + * {postQueries.map((query, index) => { + * if (query.isPending) return
  • Loading...
  • + * if (query.isError) + * return
  • Error: {query.error.message}
  • + * return
  • {query.data.title}
  • + * })} + *
+ * ) + * } + * ``` * - * return ( - *
    - * {postQueries.map((query, index) => { - * if (query.isPending) return
  • Loading...
  • - * if (query.isError) return
  • Error: {query.error.message}
  • - * return
  • {query.data.title}
  • - * })} - *
- * ) - * } - * ``` * @example - * Combining results into a single value: - * ```tsx - * import { useQueries } from '@tanstack/preact-query' + * Combining results into a single value: + * ```tsx + * import { useQueries } from '@tanstack/preact-query' * - * function Posts({ ids }: { ids: Array }) { + * function Posts({ ids }: { ids: Array }) { * const { data, isPending, isError } = useQueries({ - * queries: ids.map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * })), - * combine: (postQueries) => { - * return { - * data: postQueries.map((query) => query.data), - * isPending: postQueries.some((query) => query.isPending), - * isError: postQueries.some((query) => query.isError), - * } - * }, + * queries: ids.map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * })), + * combine: (postQueries) => { + * return { + * data: postQueries.map((query) => query.data), + * isPending: postQueries.some((query) => query.isPending), + * isError: postQueries.some((query) => query.isError), + * } + * }, * }) * * if (isPending) return 'Loading...' * if (isError) return 'Error loading posts' * * return ( - *
    - * {data.map((post) => ( - *
  • {post?.title}
  • - * ))} - *
+ *
    + * {data.map((post) => ( + *
  • {post?.title}
  • + * ))} + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The `queries` array to run, and the optional `combine` and + * `subscribed` options. + * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, + * the one from the nearest context will be used. + * @returns The combined result. Without `combine`, this is an array with all + * the query results, in the same order as the input. When `combine` is + * provided, this is the value returned by `combine` instead. + * @throws {Error} The error of the first query that should be thrown to the + * nearest error boundary (see `throwOnError`). While suspending, it throws a + * promise instead. */ export function useQueries< T extends Array, @@ -310,21 +326,26 @@ export function useQueries< ...options }: { /** - * An array with query option objects, mostly identical to `useQuery` — except that `queryClient` and - * `subscribed` aren't accepted per-query (`subscribed` is a top-level option here instead), and - * `placeholderData` accepts a {@link QueriesPlaceholderDataFunction}, which is called with `previousData` - * and `previousQuery` always `undefined`, rather than `useQuery`'s placeholder function. + * An array with query option objects, mostly identical to `useQuery` — + * except that `queryClient` and `subscribed` aren't accepted per-query + * (`subscribed` is a top-level option here instead), and `placeholderData` + * accepts a {@link QueriesPlaceholderDataFunction}, which is called with + * `previousData` and `previousQuery` always `undefined`, rather than + * `useQuery`'s placeholder function. */ queries: | readonly [...QueriesOptions] | readonly [...{ [K in keyof T]: GetUseQueryOptionsForUseQueries }] /** - * Use this to combine the results of the queries into a single value. The result will be structurally - * shared to be as referentially stable as possible. + * Use this to combine the results of the queries into a single value. The + * result will be structurally shared to be as referentially stable as + * possible. */ combine?: (result: QueriesResults) => TCombinedResult /** - * Set this to `false` to unsubscribe this observer from updates to the query cache. + * Set this to `false` to unsubscribe this observer from updates to the + * query cache. + * * @defaultValue true */ subscribed?: boolean diff --git a/packages/preact-query/src/useQuery.ts b/packages/preact-query/src/useQuery.ts index 4b87a81cee9..8b3ffcd3b5b 100644 --- a/packages/preact-query/src/useQuery.ts +++ b/packages/preact-query/src/useQuery.ts @@ -13,38 +13,46 @@ import type { } from './types' /** - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `useQuery`, with `initialData` set. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result, typed so that `status` is `success` — or `error` if a fetch attempt - * fails while keeping the existing data (`status` never resolves to `pending` in this overload's type, - * since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). + * * @example - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * }) + * function Posts() { + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * }) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) =>
  • {post.title}
  • )} - *
- *
- * ) - * } - * ``` + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) + * } + * ``` + * + * @param options - The {@link DefinedInitialDataOptions} to use — everything + * you can pass to `useQuery`, with `initialData` set. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result, typed so that `status` is `success` — or + * `error` if a fetch attempt fails while keeping the existing data (`status` + * never resolves to `pending` in this overload's type, since `initialData` + * guarantees data upfront). `isSuccess`/`isError` are derived booleans for + * convenience. + * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. */ export function useQuery< TQueryFnData = unknown, @@ -57,61 +65,66 @@ export function useQuery< ): DefinedUseQueryResult /** - * This overload is selected when `initialData` is omitted or may be `undefined`, so the resulting `data` - * can be `undefined`. - * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `useQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result. `status` is `pending` if there is no cached data to display, `error` if - * the last fetch attempt failed, or `success` if the query has data to display. `isPending`/`isSuccess`/`isError` - * are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. + * This overload is selected when `initialData` is omitted or may be + * `undefined`, so the resulting `data` can be `undefined`. + * * @example - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function Posts() { - * const { status, data, error, isFetching } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) + * function Posts() { + * const { status, data, error, isFetching } = useQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) * - * if (status === 'pending') return 'Loading...' - * if (status === 'error') return Error: {error.message} + * if (status === 'pending') return 'Loading...' + * if (status === 'error') return Error: {error.message} + * + * return ( + *
+ *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
{isFetching ? 'Background Updating...' : ' '}
+ *
+ * ) + * } + * ``` * - * return ( - *
- *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
{isFetching ? 'Background Updating...' : ' '}
- *
- * ) - * } - * ``` * @example - * The same query, checking `isPending`/`isError` instead of `status` — pick whichever reads better to you: - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * The same query, checking `isPending`/`isError` instead of `status` — pick whichever reads better to you: + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function Posts() { + * function Posts() { * const { isPending, isError, data, error } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, + * queryKey: ['posts'], + * queryFn: fetchPosts, * }) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return ( - *
    - * {data.map((post) =>
  • {post.title}
  • )} - *
+ *
    + * {data.map((post) =>
  • {post.title}
  • )} + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UndefinedInitialDataOptions} to use — everything + * you can pass to `useQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result. `status` is `pending` if there is no + * cached data to display, `error` if the last fetch attempt failed, or + * `success` if the query has data to display. + * `isPending`/`isSuccess`/`isError` are derived booleans for convenience. + * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. */ export function useQuery< TQueryFnData = unknown, @@ -124,71 +137,68 @@ export function useQuery< ): UseQueryResult /** - * Fallback overload for options whose `initialData` presence isn't statically known — for example, an - * object typed as {@link UseQueryOptions} rather than an object literal. Prefer one of the other overloads - * when possible, since they infer whether `data` can be `undefined` from `initialData` directly. - * @param options - The {@link UseQueryOptions} to use — everything you can pass to `useQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result. `status` is `pending` if there is no cached data to display, `error` if - * the last fetch attempt failed, or `success` if the query has data to display. `isPending`/`isSuccess`/`isError` - * are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. + * Fallback overload for options whose `initialData` presence isn't statically + * known — for example, an object typed as {@link UseQueryOptions} rather than an + * object literal. Prefer one of the other overloads when possible, since they + * infer whether `data` can be `undefined` from `initialData` directly. + * * @example - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function Posts() { - * const { status, data, error, isFetching } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) + * function Posts() { + * const { status, data, error, isFetching } = useQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) * - * if (status === 'pending') return 'Loading...' - * if (status === 'error') return Error: {error.message} + * if (status === 'pending') return 'Loading...' + * if (status === 'error') return Error: {error.message} + * + * return ( + *
+ *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
{isFetching ? 'Background Updating...' : ' '}
+ *
+ * ) + * } + * ``` * - * return ( - *
- *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
{isFetching ? 'Background Updating...' : ' '}
- *
- * ) - * } - * ``` * @example - * `select` derives whatever `data` a component needs from the cached value, without changing what's - * actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`: - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * `select` derives whatever `data` a component needs from the cached value, without changing what's + * actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`: + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function PostCount() { + * function PostCount() { * const { data, isPending, isError, error } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * select: (posts) => posts.length, + * queryKey: ['posts'], + * queryFn: fetchPosts, + * select: (posts) => posts.length, * }) * * if (isPending) return 'Loading...' * if (isError) return Error: {error.message} * * return {data} posts - * } - * ``` + * } + * ``` + * * @example - * A dependent query, only enabled once `postId` is set — use `isLoading`, not `isPending`, so the - * loading state doesn't show while the query is disabled: - * ```tsx - * import { useQuery } from '@tanstack/preact-query' + * A dependent query, only enabled once `postId` is set — use `isLoading`, not `isPending`, so the + * loading state doesn't show while the query is disabled: + * ```tsx + * import { useQuery } from '@tanstack/preact-query' * - * function Post({ postId }: { postId: number | undefined }) { + * function Post({ postId }: { postId: number | undefined }) { * const { data, isLoading, isError, error } = useQuery({ - * queryKey: ['post', postId], - * queryFn: () => fetchPost(postId!), - * enabled: postId != null, + * queryKey: ['post', postId], + * queryFn: () => fetchPost(postId!), + * enabled: postId != null, * }) * * if (postId == null) return 'Select a post' @@ -196,20 +206,21 @@ export function useQuery< * if (isError) return Error: {error.message} * * return

{data?.title}

- * } - * ``` + * } + * ``` + * * @example - * The same dependent query, type safe: `skipToken` disables the query without needing the - * non-null assertion above, since `queryFn` is only ever called when `postId` is defined. - * `refetch` doesn't work while `queryFn` is `skipToken` — use `enabled: false` instead if you - * need to trigger the query manually: - * ```tsx - * import { skipToken, useQuery } from '@tanstack/preact-query' - * - * function Post({ postId }: { postId: number | undefined }) { + * The same dependent query, type safe: `skipToken` disables the query without needing the + * non-null assertion above, since `queryFn` is only ever called when `postId` is defined. + * `refetch` doesn't work while `queryFn` is `skipToken` — use `enabled: false` instead if you + * need to trigger the query manually: + * ```tsx + * import { skipToken, useQuery } from '@tanstack/preact-query' + * + * function Post({ postId }: { postId: number | undefined }) { * const { data, isLoading, isError, error } = useQuery({ - * queryKey: ['post', postId], - * queryFn: postId != null ? () => fetchPost(postId) : skipToken, + * queryKey: ['post', postId], + * queryFn: postId != null ? () => fetchPost(postId) : skipToken, * }) * * if (postId == null) return 'Select a post' @@ -217,66 +228,78 @@ export function useQuery< * if (isError) return Error: {error.message} * * return

{data?.title}

- * } - * ``` + * } + * ``` + * * @example - * Seeding a detail query from an already-cached list, to skip the loading state. `initialDataUpdatedAt` carries - * over the list's own fetch time, so that if you set a `staleTime`, it's measured from when the list was - * fetched rather than from now: - * ```tsx - * import { useQuery, useQueryClient } from '@tanstack/preact-query' + * Seeding a detail query from an already-cached list, to skip the loading state. `initialDataUpdatedAt` carries + * over the list's own fetch time, so that if you set a `staleTime`, it's measured from when the list was + * fetched rather than from now: + * ```tsx + * import { useQuery, useQueryClient } from '@tanstack/preact-query' * - * function Post({ postId }: { postId: number }) { + * function Post({ postId }: { postId: number }) { * const queryClient = useQueryClient() * * const { data, isError, error } = useQuery({ - * queryKey: ['post', postId], - * queryFn: () => fetchPost(postId), - * initialData: () => - * queryClient - * .getQueryData>(['posts']) - * ?.find((post) => post.id === postId), - * initialDataUpdatedAt: () => - * queryClient.getQueryState(['posts'])?.dataUpdatedAt, + * queryKey: ['post', postId], + * queryFn: () => fetchPost(postId), + * initialData: () => + * queryClient + * .getQueryData>(['posts']) + * ?.find((post) => post.id === postId), + * initialDataUpdatedAt: () => + * queryClient.getQueryState(['posts'])?.dataUpdatedAt, * }) * * if (isError) return Error: {error.message} * * return

{data?.title}

- * } - * ``` + * } + * ``` + * * @example - * Paginated data, keeping the previous page's data visible while the next page loads: - * ```tsx - * import { keepPreviousData, useQuery } from '@tanstack/preact-query' - * import { useState } from 'preact/hooks' + * Paginated data, keeping the previous page's data visible while the next page loads: + * ```tsx + * import { keepPreviousData, useQuery } from '@tanstack/preact-query' + * import { useState } from 'preact/hooks' * - * function Posts() { + * function Posts() { * const [page, setPage] = useState(0) * * const { data, isPlaceholderData, isError, error } = useQuery({ - * queryKey: ['posts', page], - * queryFn: () => fetchPosts(page), - * placeholderData: keepPreviousData, + * queryKey: ['posts', page], + * queryFn: () => fetchPosts(page), + * placeholderData: keepPreviousData, * }) * * if (isError) return Error: {error.message} * * return ( - *
- *
    - * {data?.map((post) =>
  • {post.title}
  • )} - *
- * - *
+ *
+ *
    + * {data?.map((post) =>
  • {post.title}
  • )} + *
+ * + *
* ) - * } - * ``` + * } + * ``` + * + * @param options - The {@link UseQueryOptions} to use — everything you can pass + * to `useQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result. `status` is `pending` if there is no + * cached data to display, `error` if the last fetch attempt failed, or + * `success` if the query has data to display. + * `isPending`/`isSuccess`/`isError` are derived booleans for convenience. + * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. */ export function useQuery< TQueryFnData = unknown, diff --git a/packages/preact-query/src/useSuspenseInfiniteQuery.ts b/packages/preact-query/src/useSuspenseInfiniteQuery.ts index bed129103de..826937ff0dc 100644 --- a/packages/preact-query/src/useSuspenseInfiniteQuery.ts +++ b/packages/preact-query/src/useSuspenseInfiniteQuery.ts @@ -16,108 +16,115 @@ import type { } from './types' /** - * The options for `useSuspenseInfiniteQuery` are the same as for `useInfiniteQuery`, except for `throwOnError`, - * `enabled`, and `placeholderData`. + * The options for `useSuspenseInfiniteQuery` are the same as for + * `useInfiniteQuery`, except for `throwOnError`, `enabled`, and + * `placeholderData`. * * Caveat: cancellation does not work. - * @param options - The {@link UseSuspenseInfiniteQueryOptions} to use — the same options as `useInfiniteQuery`, minus the ones listed above. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The same object as `useInfiniteQuery`, except that `data` is guaranteed to be defined, - * `isPlaceholderData` is missing, and `status` is either `success` or `error` (with the derived flags set - * accordingly). - * @remarks Multiple suspenseful query calls in the same component suspend serially, causing a request - * waterfall — each one blocks rendering until it resolves, so the next doesn't even start fetching until - * then. There's no way to parallelize multiple infinite queries under Suspense. Also keep in mind that - * imperative fetch calls, such as `fetchNextPage`, may interfere with the default refetch behavior, - * resulting in outdated data. Make sure to call these functions only in response to user actions, or add - * conditions like `hasNextPage && !isFetching`. - * @see {@link useInfiniteQuery} for the non-Suspense version of this hook. + * + * @remarks + * Multiple suspenseful query calls in the same component suspend serially, + * causing a request waterfall — each one blocks rendering until it resolves, + * so the next doesn't even start fetching until then. There's no way to + * parallelize multiple infinite queries under Suspense. Also keep in mind + * that imperative fetch calls, such as `fetchNextPage`, may interfere with + * the default refetch behavior, resulting in outdated data. Make sure to call + * these functions only in response to user actions, or add conditions like + * `hasNextPage && !isFetching`. * @example - * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is - * required around ``. A failed background refetch instead continues to render the cached data. - * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is + * required around ``. A failed background refetch instead continues to render the cached data. + * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseInfiniteQuery, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Projects() { + * function Projects() { * // `data` is guaranteed to be defined here — no `isPending` check needed. * const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } = - * useSuspenseInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * }) + * useSuspenseInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * }) * * return ( - *
- *
    - * {data.pages.map((page) => - * page.projects.map((project) =>
  • {project.name}
  • ), - * )} - *
- * - *
+ *
+ *
    + * {data.pages.map((page) => + * page.projects.map((project) =>
  • {project.name}
  • ), + * )} + *
+ * + *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading projects...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading projects...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * + * @param options - The {@link UseSuspenseInfiniteQueryOptions} to use — the + * same options as `useInfiniteQuery`, minus the ones listed above. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The same object as `useInfiniteQuery`, except that `data` is + * guaranteed to be defined, `isPlaceholderData` is missing, and `status` is + * either `success` or `error` (with the derived flags set accordingly). + * @see {@link useInfiniteQuery} for the non-Suspense version of this hook. */ export function useSuspenseInfiniteQuery< TQueryFnData, diff --git a/packages/preact-query/src/useSuspenseQueries.ts b/packages/preact-query/src/useSuspenseQueries.ts index 481c34562b1..b5297a98d47 100644 --- a/packages/preact-query/src/useSuspenseQueries.ts +++ b/packages/preact-query/src/useSuspenseQueries.ts @@ -105,19 +105,22 @@ type GetUseSuspenseQueryResult = UseSuspenseQueryResult /** - * The `queries` array accepted by `useSuspenseQueries`. Recursively unwraps each tuple element so every - * entry's `queryFn`/`select` are inferred individually, up to 20 elements — past that, a tuple falls back to - * a single homogeneous {@link UseSuspenseQueryOptions} type. - * - * An opaque array (e.g. `unknown[]`) is returned as-is; a non-tuple array whose element type structurally - * matches a query options object is mapped per-element instead, still inferring each entry individually; any - * other non-tuple array — one whose element type doesn't match the expected options shape — falls back to - * that same homogeneous options type too. + * The `queries` array accepted by `useSuspenseQueries`. Recursively unwraps + * each tuple element so every entry's `queryFn`/`select` are inferred + * individually, up to 20 elements — past that, a tuple falls back to a single + * homogeneous {@link UseSuspenseQueryOptions} type. + * + * An opaque array (e.g. `unknown[]`) is returned as-is; a non-tuple array whose + * element type structurally matches a query options object is mapped + * per-element instead, still inferring each entry individually; any other + * non-tuple array — one whose element type doesn't match the expected options + * shape — falls back to that same homogeneous options type too. + * * @template T - The type of the `queries` array as written at the call site. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant - * to be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type SuspenseQueriesOptions< T extends Array, @@ -154,15 +157,19 @@ export type SuspenseQueriesOptions< Array /** - * The result type returned by `useSuspenseQueries`, when no `combine` is provided. Mirrors - * {@link SuspenseQueriesOptions}: each tuple element's result type is inferred individually, up to 20 elements. - * A non-tuple array is mapped per-element instead, still inferring each entry individually; only past 20 - * elements does this fall back to a single homogeneous {@link UseSuspenseQueryResult} type. - * @template T - The type of the `queries` array, as inferred by {@link SuspenseQueriesOptions}. - * @template TResults - The internal accumulator that this type builds during recursion. It is not meant - * to be set explicitly. - * @template TDepth - The internal recursion-depth counter, checked against the 20-element limit. It is not - * meant to be set explicitly. + * The result type returned by `useSuspenseQueries`, when no `combine` is + * provided. Mirrors {@link SuspenseQueriesOptions}: each tuple element's result + * type is inferred individually, up to 20 elements. A non-tuple array is mapped + * per-element instead, still inferring each entry individually; only past 20 + * elements does this fall back to a single homogeneous + * {@link UseSuspenseQueryResult} type. + * + * @template T - The type of the `queries` array, as inferred by + * {@link SuspenseQueriesOptions}. + * @template TResults - The internal accumulator that this type builds during + * recursion. It is not meant to be set explicitly. + * @template TDepth - The internal recursion-depth counter, checked against the + * 20-element limit. It is not meant to be set explicitly. */ export type SuspenseQueriesResults< T extends Array, @@ -183,241 +190,247 @@ export type SuspenseQueriesResults< : { [K in keyof T]: GetUseSuspenseQueryResult } /** - * The options for `useSuspenseQueries` are the same as for `useQueries`, except that the top-level `subscribed` - * option isn't supported, and each `query` can't have `throwOnError`, `enabled`, or `placeholderData`. - * @param options - The `queries` array to run in Suspense, and an optional `combine` function. - * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, the one from the nearest context - * will be used. - * @returns The same structure as `useQueries`, except that for each `query`, `data` is guaranteed to be - * defined, `isPlaceholderData` is missing, and `status` is either `success` or `error` (with the derived - * flags set accordingly). - * - * Caveat: the component will only re-mount after all queries have finished loading. Hence, if a query has gone - * stale in the time it took for all the queries to complete, it will be fetched again at re-mount. To avoid - * this, make sure to set a high enough `staleTime`. Cancellation does not work. + * The options for `useSuspenseQueries` are the same as for `useQueries`, except + * that the top-level `subscribed` option isn't supported, and each `query` + * can't have `throwOnError`, `enabled`, or `placeholderData`. + * * @example - * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is - * required around ``. A failed background refetch instead continues to render the cached data. - * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is + * required around ``. A failed background refetch instead continues to render the cached data. + * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseQueries, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Posts({ ids }: { ids: Array }) { + * function Posts({ ids }: { ids: Array }) { * // Every result is guaranteed to be defined — no per-query `isPending` check needed. * const postQueries = useSuspenseQueries({ - * queries: ids.map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * })), + * queries: ids.map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * })), * }) * * return ( - *
    - * {postQueries.map((query) => ( - *
  • {query.data.title}
  • - * ))} - *
+ *
    + * {postQueries.map((query) => ( + *
  • {query.data.title}
  • + * ))} + *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading posts...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading posts...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * * @example - * Several different queries — use `useSuspenseQueries` instead of multiple `useSuspenseQuery` calls, so - * they fetch in parallel rather than suspending one after another: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * Several different queries — use `useSuspenseQueries` instead of multiple `useSuspenseQuery` calls, so + * they fetch in parallel rather than suspending one after another: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseQueries, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Dashboard() { + * function Dashboard() { * const [usersQuery, teamsQuery, projectsQuery] = useSuspenseQueries({ - * queries: [ - * { queryKey: ['users'], queryFn: fetchUsers }, - * { queryKey: ['teams'], queryFn: fetchTeams }, - * { queryKey: ['projects'], queryFn: fetchProjects }, - * ], + * queries: [ + * { queryKey: ['users'], queryFn: fetchUsers }, + * { queryKey: ['teams'], queryFn: fetchTeams }, + * { queryKey: ['projects'], queryFn: fetchProjects }, + * ], * }) * * return ( - *
- * - * - * - *
+ *
+ * + * + * + *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading dashboard...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading dashboard...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * * @example - * `combine`s the results into a single boolean, so `Refresh` only re-renders when that boolean changes, - * not on every individual query update. This overload is the only one that accepts `combine`: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * `combine`s the results into a single boolean, so `Refresh` only re-renders when that boolean changes, + * not on every individual query update. This overload is the only one that accepts `combine`: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseQueries, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Refresh() { + * function Refresh() { * const anyFetching = useSuspenseQueries({ - * queries: [ - * { queryKey: ['users'], queryFn: fetchUsers }, - * { queryKey: ['teams'], queryFn: fetchTeams }, - * ], - * combine: (results) => results.some((result) => result.isFetching), + * queries: [ + * { queryKey: ['users'], queryFn: fetchUsers }, + * { queryKey: ['teams'], queryFn: fetchTeams }, + * ], + * combine: (results) => results.some((result) => result.isFetching), * }) * * return anyFetching ? Refreshing… : null - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading dashboard...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading dashboard...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * + * @param options - The `queries` array to run in Suspense, and an optional + * `combine` function. + * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, + * the one from the nearest context will be used. + * @returns The same structure as `useQueries`, except that for each `query`, + * `data` is guaranteed to be defined, `isPlaceholderData` is missing, and + * `status` is either `success` or `error` (with the derived flags set + * accordingly). Caveat: the component will only re-mount after all queries + * have finished loading. Hence, if a query has gone stale in the time it took + * for all the queries to complete, it will be fetched again at re-mount. To + * avoid this, make sure to set a high enough `staleTime`. Cancellation does + * not work. */ export function useSuspenseQueries< T extends Array, TCombinedResult = SuspenseQueriesResults, >( options: { - /** - * An array with query option objects identical to `useSuspenseQuery`. - */ + /** An array with query option objects identical to `useSuspenseQuery`. */ queries: | readonly [...SuspenseQueriesOptions] | readonly [...{ [K in keyof T]: GetUseSuspenseQueryOptions }] /** - * Use this to combine the results of the queries into a single value. The result will be structurally - * shared to be as referentially stable as possible. + * Use this to combine the results of the queries into a single value. The + * result will be structurally shared to be as referentially stable as + * possible. */ combine?: (result: SuspenseQueriesResults) => TCombinedResult }, @@ -425,174 +438,179 @@ export function useSuspenseQueries< ): TCombinedResult /** - * The options for `useSuspenseQueries` are the same as for `useQueries`, except that the top-level `subscribed` - * option isn't supported, and each `query` can't have `throwOnError`, `enabled`, or `placeholderData`. - * @param options - The `queries` array to run in Suspense, and an optional `combine` function. - * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, the one from the nearest context - * will be used. - * @returns The same structure as `useQueries`, except that for each `query`, `data` is guaranteed to be - * defined, `isPlaceholderData` is missing, and `status` is either `success` or `error` (with the derived - * flags set accordingly). - * - * Caveat: the component will only re-mount after all queries have finished loading. Hence, if a query has gone - * stale in the time it took for all the queries to complete, it will be fetched again at re-mount. To avoid - * this, make sure to set a high enough `staleTime`. Cancellation does not work. + * The options for `useSuspenseQueries` are the same as for `useQueries`, except + * that the top-level `subscribed` option isn't supported, and each `query` + * can't have `throwOnError`, `enabled`, or `placeholderData`. + * * @example - * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is - * required around ``. A failed background refetch instead continues to render the cached data. - * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * The query error is thrown if a fetch fails and no cached data exists yet, so an error boundary is + * required around ``. A failed background refetch instead continues to render the cached data. + * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseQueries, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Posts({ ids }: { ids: Array }) { + * function Posts({ ids }: { ids: Array }) { * // Every result is guaranteed to be defined — no per-query `isPending` check needed. * const postQueries = useSuspenseQueries({ - * queries: ids.map((id) => ({ - * queryKey: ['post', id], - * queryFn: () => fetchPost(id), - * })), + * queries: ids.map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * })), * }) * * return ( - *
    - * {postQueries.map((query) => ( - *
  • {query.data.title}
  • - * ))} - *
+ *
    + * {postQueries.map((query) => ( + *
  • {query.data.title}
  • + * ))} + *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading posts...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading posts...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * * @example - * Several different queries — use `useSuspenseQueries` instead of multiple `useSuspenseQuery` calls, so - * they fetch in parallel rather than suspending one after another: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { + * Several different queries — use `useSuspenseQueries` instead of multiple `useSuspenseQuery` calls, so + * they fetch in parallel rather than suspending one after another: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { * QueryErrorResetBoundary, * useSuspenseQueries, - * } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Dashboard() { + * function Dashboard() { * const [usersQuery, teamsQuery, projectsQuery] = useSuspenseQueries({ - * queries: [ - * { queryKey: ['users'], queryFn: fetchUsers }, - * { queryKey: ['teams'], queryFn: fetchTeams }, - * { queryKey: ['projects'], queryFn: fetchProjects }, - * ], + * queries: [ + * { queryKey: ['users'], queryFn: fetchUsers }, + * { queryKey: ['teams'], queryFn: fetchTeams }, + * { queryKey: ['projects'], queryFn: fetchProjects }, + * ], * }) * * return ( - *
- * - * - * - *
+ *
+ * + * + * + *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading dashboard...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading dashboard...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * + * @param options - The `queries` array to run in Suspense, and an optional + * `combine` function. + * @param queryClient - Use this to provide a custom `QueryClient`. Otherwise, + * the one from the nearest context will be used. + * @returns The same structure as `useQueries`, except that for each `query`, + * `data` is guaranteed to be defined, `isPlaceholderData` is missing, and + * `status` is either `success` or `error` (with the derived flags set + * accordingly). Caveat: the component will only re-mount after all queries + * have finished loading. Hence, if a query has gone stale in the time it took + * for all the queries to complete, it will be fetched again at re-mount. To + * avoid this, make sure to set a high enough `staleTime`. Cancellation does + * not work. */ export function useSuspenseQueries< T extends Array, TCombinedResult = SuspenseQueriesResults, >( options: { - /** - * An array with query option objects identical to `useSuspenseQuery`. - */ + /** An array with query option objects identical to `useSuspenseQuery`. */ queries: readonly [...SuspenseQueriesOptions] /** - * Use this to combine the results of the queries into a single value. The result will be structurally - * shared to be as referentially stable as possible. + * Use this to combine the results of the queries into a single value. The + * result will be structurally shared to be as referentially stable as + * possible. */ combine?: (result: SuspenseQueriesResults) => TCombinedResult }, diff --git a/packages/preact-query/src/useSuspenseQuery.ts b/packages/preact-query/src/useSuspenseQuery.ts index c5f1815ea42..7fcc1330a2e 100644 --- a/packages/preact-query/src/useSuspenseQuery.ts +++ b/packages/preact-query/src/useSuspenseQuery.ts @@ -6,89 +6,95 @@ import type { DefaultError, QueryClient, QueryKey } from '@tanstack/query-core' import type { UseSuspenseQueryOptions, UseSuspenseQueryResult } from './types' /** - * The options for `useSuspenseQuery` are the same as for `useQuery`, except for `throwOnError`, `enabled`, and - * `placeholderData`. + * The options for `useSuspenseQuery` are the same as for `useQuery`, except for + * `throwOnError`, `enabled`, and `placeholderData`. * * Caveat: cancellation does not work. - * @param options - The {@link UseSuspenseQueryOptions} to use — the same options as `useQuery`, minus the ones listed above. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The same object as `useQuery`, except that `data` is guaranteed to be defined, `isPlaceholderData` - * is missing, and `status` is either `success` or `error` (with the derived flags set accordingly). - * @remarks Multiple `useSuspenseQuery` calls in the same component suspend serially, causing a request - * waterfall — each one blocks rendering until it resolves, so the next doesn't even start fetching until then. - * Use {@link useSuspenseQueries} instead when you have more than one suspenseful query in a component, so they - * fetch in parallel. + * + * @remarks + * Multiple `useSuspenseQuery` calls in the same component suspend serially, + * causing a request waterfall — each one blocks rendering until it resolves, + * so the next doesn't even start fetching until then. Use + * {@link useSuspenseQueries} instead when you have more than one suspenseful + * query in a component, so they fetch in parallel. * @example - * The query error is thrown if the fetch fails and no cached data exists yet, so an error boundary is - * required around ``. A failed background refetch instead continues to render the cached data. - * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: - * ```tsx - * import { Suspense } from 'preact/compat' - * import { useErrorBoundary } from 'preact/hooks' - * import { QueryErrorResetBoundary, useSuspenseQuery } from '@tanstack/preact-query' - * import type { ComponentChildren } from 'preact' + * The query error is thrown if the fetch fails and no cached data exists yet, so an error boundary is + * required around ``. A failed background refetch instead continues to render the cached data. + * Use {@link QueryErrorResetBoundary} to let the user retry after such an error: + * ```tsx + * import { Suspense } from 'preact/compat' + * import { useErrorBoundary } from 'preact/hooks' + * import { QueryErrorResetBoundary, useSuspenseQuery } from '@tanstack/preact-query' + * import type { ComponentChildren } from 'preact' * - * function Posts() { + * function Posts() { * // `data` is guaranteed to be defined here — no `isPending` check needed. * const { data, isFetching } = useSuspenseQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, + * queryKey: ['posts'], + * queryFn: fetchPosts, * }) * * return ( - *
- *

Posts {isFetching ? '(refreshing...)' : null}

- *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
+ *
+ *

Posts {isFetching ? '(refreshing...)' : null}

+ *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
* ) - * } + * } * - * function App() { + * function App() { * return ( - * - * {({ reset }) => ( - * ( - *
- * There was an error! - * - *
- * )} - * > - * Loading posts...}> - * - * - *
- * )} - *
+ * + * {({ reset }) => ( + * ( + *
+ * There was an error! + * + *
+ * )} + * > + * Loading posts...}> + * + * + *
+ * )} + *
* ) - * } + * } * - * function ErrorBoundary({ + * function ErrorBoundary({ * children, * onReset, * fallbackRender, - * }: { + * }: { * children: ComponentChildren * onReset: () => void * fallbackRender: (props: { - * error: Error - * resetErrorBoundary: () => void + * error: Error + * resetErrorBoundary: () => void * }) => ComponentChildren - * }) { + * }) { * const [error, resetErrorBoundary] = useErrorBoundary(() => onReset()) * * if (error) return fallbackRender({ error, resetErrorBoundary }) * * return children - * } - * ``` + * } + * ``` + * + * @param options - The {@link UseSuspenseQueryOptions} to use — the same + * options as `useQuery`, minus the ones listed above. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The same object as `useQuery`, except that `data` is guaranteed to + * be defined, `isPlaceholderData` is missing, and `status` is either + * `success` or `error` (with the derived flags set accordingly). */ export function useSuspenseQuery< TQueryFnData = unknown, diff --git a/packages/preact-query/src/utils.ts b/packages/preact-query/src/utils.ts index 61100886527..78cbced09f8 100644 --- a/packages/preact-query/src/utils.ts +++ b/packages/preact-query/src/utils.ts @@ -1,10 +1,13 @@ import { useEffect, useLayoutEffect, useRef, useState } from 'preact/hooks' /** - * This is taken from https://github.com/preactjs/preact/blob/main/compat/src/hooks.js#L8-L54 - * which is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84 - * on a high level this cuts out the warnings, ... and attempts a smaller implementation. - * This way we don't have to import preact/compat with side effects + * This is taken from + * https://github.com/preactjs/preact/blob/main/compat/src/hooks.js#L8-L54 which + * is taken from + * https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84 + * on a high level this cuts out the warnings, ... and attempts a smaller + * implementation. This way we don't have to import preact/compat with side + * effects */ type InternalStore = { _value: any @@ -14,8 +17,11 @@ type StoreRef = { _instance: InternalStore } /** - * Subscribes to an external store and returns its current snapshot, re-rendering when it changes. - * @param subscribe - Subscribes to the store, and returns a function that unsubscribes. + * Subscribes to an external store and returns its current snapshot, + * re-rendering when it changes. + * + * @param subscribe - Subscribes to the store, and returns a function that + * unsubscribes. * @param getSnapshot - Returns the current snapshot of the store. * @returns The current snapshot. */ @@ -55,7 +61,9 @@ export function useSyncExternalStore( /** * Checks whether the store's snapshot changed since it was last read. - * @param inst - The stored snapshot and the function that reads the current one. + * + * @param inst - The stored snapshot and the function that reads the current + * one. * @returns `true` if the current snapshot differs, or if reading it throws. */ function didSnapshotChange(inst: { @@ -73,9 +81,11 @@ function didSnapshotChange(inst: { } /** - * Like {@link useSyncExternalStore}, but returns a selected part of the snapshot, only updating it - * when `isEqual` reports a change. - * @param subscribe - Subscribes to the store, and returns a function that unsubscribes. + * Like {@link useSyncExternalStore}, but returns a selected part of the + * snapshot, only updating it when `isEqual` reports a change. + * + * @param subscribe - Subscribes to the store, and returns a function that + * unsubscribes. * @param getSnapshot - Returns the current snapshot of the store. * @param selector - Selects the part of the snapshot to return. * @param isEqual - Compares the previous and the new selection. diff --git a/packages/query-async-storage-persister/src/asyncThrottle.ts b/packages/query-async-storage-persister/src/asyncThrottle.ts index ef28ec93a4e..ee2318228b6 100644 --- a/packages/query-async-storage-persister/src/asyncThrottle.ts +++ b/packages/query-async-storage-persister/src/asyncThrottle.ts @@ -7,11 +7,13 @@ interface AsyncThrottleOptions { } /** - * Wraps an async function so it runs at most once per `interval`, never concurrently, and with the - * arguments of the latest call. Calls made while a run is scheduled only update those arguments. + * Wraps an async function so it runs at most once per `interval`, never + * concurrently, and with the arguments of the latest call. Calls made while a + * run is scheduled only update those arguments. + * * @param func - The async function to throttle. - * @param options - The `interval` between runs in milliseconds, and `onError`, called when `func` - * rejects. + * @param options - The `interval` between runs in milliseconds, and `onError`, + * called when `func` rejects. * @returns The throttled function. * @throws {Error} If `func` is not a function. */ diff --git a/packages/query-async-storage-persister/src/index.ts b/packages/query-async-storage-persister/src/index.ts index 24108086ff5..aa04e0db395 100644 --- a/packages/query-async-storage-persister/src/index.ts +++ b/packages/query-async-storage-persister/src/index.ts @@ -9,8 +9,8 @@ import type { } from '@tanstack/query-persist-client-core' /** - * Called when saving the persisted client fails. Returns, or resolves to, a smaller client to try - * saving again, or `undefined` to give up. + * Called when saving the persisted client fails. Returns, or resolves to, a + * smaller client to try saving again, or `undefined` to give up. */ export type AsyncPersistRetryer = (props: { persistedClient: PersistedClient @@ -20,25 +20,24 @@ export type AsyncPersistRetryer = (props: { interface CreateAsyncStoragePersisterOptions { /** - * The storage client used for setting and retrieving items from cache. - * For SSR pass in `undefined`. Note that window.localStorage can be - * `null` in Android WebViews depending on how they are configured. + * The storage client used for setting and retrieving items from cache. For + * SSR pass in `undefined`. Note that window.localStorage can be `null` in + * Android WebViews depending on how they are configured. */ storage: AsyncStorage | undefined | null /** The key to use when storing the cache */ key?: string - /** - * To avoid spamming, - * pass a time in ms to throttle saving the cache to disk - */ + /** To avoid spamming, pass a time in ms to throttle saving the cache to disk */ throttleTime?: number /** * How to serialize the data to storage. + * * @default `JSON.stringify` */ serialize?: (client: PersistedClient) => MaybePromise /** * How to deserialize the data from storage. + * * @default `JSON.parse` */ deserialize?: (cachedString: string) => MaybePromise @@ -47,12 +46,14 @@ interface CreateAsyncStoragePersisterOptions { } /** - * Creates a persister that saves the client to an asynchronous storage such as `AsyncStorage`, - * throttled by `throttleTime`. If saving fails, `retry` can return a smaller client to try again. - * @param options - The `storage` to persist to, the `key`, `throttleTime`, `serialize`, - * `deserialize`, and `retry` options. - * @returns A persister that saves, restores, and removes the client in `storage`. Without - * `storage`, its methods do nothing. + * Creates a persister that saves the client to an asynchronous storage such as + * `AsyncStorage`, throttled by `throttleTime`. If saving fails, `retry` can + * return a smaller client to try again. + * + * @param options - The `storage` to persist to, the `key`, `throttleTime`, + * `serialize`, `deserialize`, and `retry` options. + * @returns A persister that saves, restores, and removes the client in + * `storage`. Without `storage`, its methods do nothing. */ export const createAsyncStoragePersister = ({ storage, diff --git a/packages/query-async-storage-persister/src/utils.ts b/packages/query-async-storage-persister/src/utils.ts index 988c820d6ab..4ce7a74cd2c 100644 --- a/packages/query-async-storage-persister/src/utils.ts +++ b/packages/query-async-storage-persister/src/utils.ts @@ -1,6 +1,4 @@ -/** - * A function that does nothing. - */ +/** A function that does nothing. */ export function noop(): void export function noop(): undefined export function noop() {} diff --git a/packages/query-broadcast-client-experimental/src/index.ts b/packages/query-broadcast-client-experimental/src/index.ts index c292b72353b..0c0ce69fe6e 100644 --- a/packages/query-broadcast-client-experimental/src/index.ts +++ b/packages/query-broadcast-client-experimental/src/index.ts @@ -4,21 +4,15 @@ import type { QueryClient, QueryKey } from '@tanstack/query-core' /** * Metadata describing a broadcast that failed to be delivered to other tabs. - * Passed to {@link BroadcastQueryClientOptions.onBroadcastError} so callers - * can correlate failures with the originating query. + * Passed to {@link BroadcastQueryClientOptions.onBroadcastError} so callers can + * correlate failures with the originating query. */ export interface BroadcastErrorEvent { - /** - * The kind of cache event that was being broadcast. - */ + /** The kind of cache event that was being broadcast. */ type: 'updated' | 'removed' | 'added' - /** - * The hash of the query the broadcast was about. - */ + /** The hash of the query the broadcast was about. */ queryHash: string - /** - * The key of the query the broadcast was about. - */ + /** The key of the query the broadcast was about. */ queryKey: QueryKey } @@ -32,16 +26,17 @@ interface BroadcastQueryClientOptions { queryClient: QueryClient /** * Unique channel name used to communicate between tabs and windows. + * * @default 'tanstack-query' */ broadcastChannel?: string /** Options forwarded to the underlying `BroadcastChannel`. */ options?: BroadcastChannelOptions /** - * Called when a query event fails to broadcast to other tabs — most - * commonly because the query's `state.data`, `state.error`, or `queryKey` - * contains a value the structured-clone algorithm cannot serialize - * (e.g. `ReadableStream`, `File`, functions, Vue `reactive` proxies). + * Called when a query event fails to broadcast to other tabs — most commonly + * because the query's `state.data`, `state.error`, or `queryKey` contains a + * value the structured-clone algorithm cannot serialize (e.g. + * `ReadableStream`, `File`, functions, Vue `reactive` proxies). * * Provide this to route failures to an error tracker. If omitted, a * `console.warn` is emitted in development so failures are never silent. @@ -56,11 +51,13 @@ interface BroadcastQueryClientOptions { } /** - * Syncs a client's query cache with the caches of other tabs and windows through a - * `BroadcastChannel`: added queries, successful updates, and removals of queries that have - * observers are broadcast, and those received from other tabs are applied. - * @param options - The `queryClient` to sync, the `broadcastChannel` name, the channel `options`, - * and the `onBroadcastError` callback. + * Syncs a client's query cache with the caches of other tabs and windows + * through a `BroadcastChannel`: added queries, successful updates, and removals + * of queries that have observers are broadcast, and those received from other + * tabs are applied. + * + * @param options - The `queryClient` to sync, the `broadcastChannel` name, the + * channel `options`, and the `onBroadcastError` callback. * @returns A function that stops syncing and closes the channel. */ export function broadcastQueryClient({ diff --git a/packages/query-codemods/src/utils/index.cjs b/packages/query-codemods/src/utils/index.cjs index a652e23b0cf..31784bdc2d3 100644 --- a/packages/query-codemods/src/utils/index.cjs +++ b/packages/query-codemods/src/utils/index.cjs @@ -38,8 +38,9 @@ module.exports = ({ root, jscodeshift }) => { } /** - * First, we search for the namespace import identifier because if we have any, we assume the consumer uses - * namespace imports. In this case, we won't search for named imports at all. + * First, we search for the namespace import identifier because if we have + * any, we assume the consumer uses namespace imports. In this case, we + * won't search for named imports at all. */ const namespaceImportIdentifier = findNamespaceImportIdentifier() diff --git a/packages/query-codemods/src/utils/transformers/query-cache-transformer.cjs b/packages/query-codemods/src/utils/transformers/query-cache-transformer.cjs index e20bc01fa74..46b545993dd 100644 --- a/packages/query-codemods/src/utils/transformers/query-cache-transformer.cjs +++ b/packages/query-codemods/src/utils/transformers/query-cache-transformer.cjs @@ -63,14 +63,16 @@ module.exports = ({ const findQueryCacheMethodCalls = (importIdentifiers) => { /** - * Here we collect all query client instantiations. We have to make aware of them because the query cache can be - * accessed by the query client as well. + * Here we collect all query client instantiations. We have to make aware of + * them because the query cache can be accessed by the query client as + * well. */ const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers(importIdentifiers) /** - * Here we collect all query cache instantiations. The reason is simple: the methods can be called on query cache - * instances, to locate the possible usages we need to be aware of the identifier names. + * Here we collect all query cache instantiations. The reason is simple: the + * methods can be called on query cache instances, to locate the possible + * usages we need to be aware of the identifier names. */ const queryCacheIdentifiers = findQueryCacheInstantiations( importIdentifiers, diff --git a/packages/query-codemods/src/utils/transformers/query-client-transformer.cjs b/packages/query-codemods/src/utils/transformers/query-client-transformer.cjs index 8282940da69..ce8f908ea10 100644 --- a/packages/query-codemods/src/utils/transformers/query-client-transformer.cjs +++ b/packages/query-codemods/src/utils/transformers/query-client-transformer.cjs @@ -9,8 +9,8 @@ module.exports = ({ const findQueryClientMethodCalls = (importIdentifiers, methods) => { /** - * Here we collect all query client instantiations. We have to make aware of them because some method calls might - * be invoked on these instances. + * Here we collect all query client instantiations. We have to make aware of + * them because some method calls might be invoked on these instances. */ const queryClientIdentifiers = utils.queryClient.findQueryClientIdentifiers(importIdentifiers) diff --git a/packages/query-codemods/src/v4/key-transformation.cjs b/packages/query-codemods/src/v4/key-transformation.cjs index ad62c084a5f..c14a190cb37 100644 --- a/packages/query-codemods/src/v4/key-transformation.cjs +++ b/packages/query-codemods/src/v4/key-transformation.cjs @@ -61,8 +61,8 @@ const transformUseQueriesUsages = ({ }) const replacer = ({ node }) => { /** - * When the node doesn't have the 'original' property, that means the codemod has been already applied, - * so we don't need to do any changes. + * When the node doesn't have the 'original' property, that means the + * codemod has been already applied, so we don't need to do any changes. */ if (!node.original) { return node diff --git a/packages/query-codemods/src/v5/is-loading/is-loading.cjs b/packages/query-codemods/src/v5/is-loading/is-loading.cjs index eb7f1b0110c..f573dcfca0b 100644 --- a/packages/query-codemods/src/v5/is-loading/is-loading.cjs +++ b/packages/query-codemods/src/v5/is-loading/is-loading.cjs @@ -10,12 +10,17 @@ const newName = 'isPending' * @param {Object} utils * @param {import('jscodeshift').Collection} root * @param {string} filePath - * @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray, hooks: ReadonlyArray}} config + * @param {{ + * keyName: 'mutationKey' | 'queryKey' + * queryClientMethods: ReadonlyArray + * hooks: ReadonlyArray + * }} config */ const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => { /** - * @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node - * @returns {{start: number, end: number}} + * @param {import('jscodeshift').CallExpression + * | import('jscodeshift').ExpressionStatement} node + * @returns {{ start: number; end: number }} */ const getNodeLocation = (node) => { const location = utils.isCallExpression(node) ? node.callee.loc : node.loc @@ -75,7 +80,7 @@ const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => { /** * @param {import('jscodeshift').ObjectPattern} node - * @returns {import('jscodeshift').ObjectProperty|null} + * @returns {import('jscodeshift').ObjectProperty | null} */ const findIsLoadingObjectPropertyInObjectPattern = (node) => { return ( @@ -92,7 +97,7 @@ const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => { /** * @param {import('jscodeshift').ObjectPattern} node - * @returns {import('jscodeshift').RestElement|null} + * @returns {import('jscodeshift').RestElement | null} */ const findRestElementInObjectPattern = (node) => { return ( diff --git a/packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs b/packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs index 3f3e3b7df70..b5105b67090 100644 --- a/packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs +++ b/packages/query-codemods/src/v5/keep-previous-data/keep-previous-data.cjs @@ -8,12 +8,17 @@ const AlreadyHasPlaceholderDataProperty = require('./utils/already-has-placehold * @param {Object} utils * @param {import('jscodeshift').Collection} root * @param {string} filePath - * @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray, hooks: ReadonlyArray}} config + * @param {{ + * keyName: 'mutationKey' | 'queryKey' + * queryClientMethods: ReadonlyArray + * hooks: ReadonlyArray + * }} config */ const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => { /** - * @param {import('jscodeshift').CallExpression | import('jscodeshift').ExpressionStatement} node - * @returns {{start: number, end: number}} + * @param {import('jscodeshift').CallExpression + * | import('jscodeshift').ExpressionStatement} node + * @returns {{ start: number; end: number }} */ const getNodeLocation = (node) => { const location = utils.isCallExpression(node) ? node.callee.loc : node.loc @@ -47,7 +52,7 @@ const transformUsages = ({ jscodeshift, utils, root, filePath, config }) => { /** * @param {import('jscodeshift').ObjectExpression} objectExpression - * @returns {Array} + * @returns {import('jscodeshift').ObjectProperty[]} */ const filterKeepPreviousDataProperty = (objectExpression) => { return objectExpression.properties.filter((objectProperty) => { diff --git a/packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs b/packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs index 33e098b7776..bd6564c0152 100644 --- a/packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs +++ b/packages/query-codemods/src/v5/remove-overloads/transformers/filter-aware-usage-transformer.cjs @@ -9,7 +9,12 @@ const createUseQueryLikeTransformer = require('../../../utils/transformers/use-q * @param {Object} utils * @param {import('jscodeshift').Collection} root * @param {string} filePath - * @param {{keyName: "mutationKey"|"queryKey", fnName: "mutationFn"|"queryFn", queryClientMethods: ReadonlyArray, hooks: ReadonlyArray}} config + * @param {{ + * keyName: 'mutationKey' | 'queryKey' + * fnName: 'mutationFn' | 'queryFn' + * queryClientMethods: ReadonlyArray + * hooks: ReadonlyArray + * }} config */ const transformFilterAwareUsages = ({ jscodeshift, @@ -22,8 +27,8 @@ const transformFilterAwareUsages = ({ /** * @param {import('jscodeshift').CallExpression} node - * @param {"mutationKey"|"queryKey"} keyName - * @param {"mutationFn"|"queryFn"} fnName + * @param {'mutationKey' | 'queryKey'} keyName + * @param {'mutationFn' | 'queryFn'} fnName * @returns {boolean} */ const canSkipReplacement = (node, keyName, fnName) => { @@ -38,8 +43,9 @@ const transformFilterAwareUsages = ({ ) /** - * This call has at least one argument. If it's an object expression and contains the "queryKey" or "mutationKey" - * field, the transformation can be skipped, because it's already matching the expected signature. + * This call has at least one argument. If it's an object expression and + * contains the "queryKey" or "mutationKey" field, the transformation can be + * skipped, because it's already matching the expected signature. */ return ( callArguments.length > 0 && @@ -49,8 +55,8 @@ const transformFilterAwareUsages = ({ } /** - * This function checks whether the given object property is a spread element or a property that's not named - * "queryKey" or "mutationKey". + * This function checks whether the given object property is a spread element + * or a property that's not named "queryKey" or "mutationKey". * * @param {import('jscodeshift').ObjectProperty} property * @returns {boolean} @@ -96,7 +102,8 @@ const transformFilterAwareUsages = ({ /** * Here we attempt to determine the first parameter of the function call. - * If it's a function definition, we can create an object property from it (the mutation fn). + * If it's a function definition, we can create an object property from it + * (the mutation fn). */ const firstArgument = node.arguments[0] if (isFunctionDefinition(firstArgument)) { @@ -132,10 +139,11 @@ const transformFilterAwareUsages = ({ } /** - * If, instead, the first parameter is an array expression or an identifier that references - * an array expression, then we create an object property from it (the query or mutation key). + * If, instead, the first parameter is an array expression or an + * identifier that references an array expression, then we create an + * object property from it (the query or mutation key). * - * @type {import('jscodeshift').Property|undefined} + * @type {import('jscodeshift').Property | undefined} */ const keyProperty = v5Utils.transformArgumentToKey( path, @@ -145,8 +153,9 @@ const transformFilterAwareUsages = ({ ) /** - * The first parameter couldn't be transformed into an object property, so it's time to throw an exception, - * it will notify the consumers that they need to rewrite this usage manually. + * The first parameter couldn't be transformed into an object property, so + * it's time to throw an exception, it will notify the consumers that they + * need to rewrite this usage manually. */ if (!keyProperty) { const secondArgument = @@ -222,9 +231,10 @@ const transformFilterAwareUsages = ({ } /** - * If it has a second argument, and it's an object expression, then we get the properties from it - * (except the "queryKey" or "mutationKey" properties), because these arguments will also be moved to the - * newly created object expression. + * If it has a second argument, and it's an object expression, then we + * get the properties from it (except the "queryKey" or "mutationKey" + * properties), because these arguments will also be moved to the newly + * created object expression. */ if (utils.isObjectExpression(secondParameter)) { v5Utils.copyPropertiesFromSource( diff --git a/packages/query-codemods/src/v5/remove-overloads/transformers/query-fn-aware-usage-transformer.cjs b/packages/query-codemods/src/v5/remove-overloads/transformers/query-fn-aware-usage-transformer.cjs index 3f29d416618..ad936fd5747 100644 --- a/packages/query-codemods/src/v5/remove-overloads/transformers/query-fn-aware-usage-transformer.cjs +++ b/packages/query-codemods/src/v5/remove-overloads/transformers/query-fn-aware-usage-transformer.cjs @@ -7,7 +7,11 @@ const createQueryClientTransformer = require('../../../utils/transformers/query- * @param {Object} utils * @param {import('jscodeshift').Collection} root * @param {string} filePath - * @param {{keyName: "mutationKey"|"queryKey", queryClientMethods: ReadonlyArray, hooks: ReadonlyArray}} config + * @param {{ + * keyName: 'mutationKey' | 'queryKey' + * queryClientMethods: ReadonlyArray + * hooks: ReadonlyArray + * }} config */ const transformQueryFnAwareUsages = ({ jscodeshift, diff --git a/packages/query-codemods/src/v5/remove-overloads/utils/index.cjs b/packages/query-codemods/src/v5/remove-overloads/utils/index.cjs index 5e81bf4469a..56610fd3db7 100644 --- a/packages/query-codemods/src/v5/remove-overloads/utils/index.cjs +++ b/packages/query-codemods/src/v5/remove-overloads/utils/index.cjs @@ -2,7 +2,6 @@ const UnknownUsageError = require('./unknown-usage-error.cjs') module.exports = ({ jscodeshift, utils }) => { /** - * * @param {import('jscodeshift').ObjectExpression} source * @param {import('jscodeshift').ObjectExpression} target * @param {(node: import('jscodeshift').Node) => boolean} predicate @@ -19,20 +18,20 @@ module.exports = ({ jscodeshift, utils }) => { * @param {import('jscodeshift').NodePath} path * @param {string} argumentName * @param {string} filePath - * @returns {*} + * @returns {any} */ const getBindingFromScope = (path, argumentName, filePath) => { /** - * If the current scope contains the declaration then we can use the actual one else we attempt to find the - * binding from above. + * If the current scope contains the declaration then we can use the actual + * one else we attempt to find the binding from above. */ const scope = path.scope.declares(argumentName) ? path.scope : path.scope.lookup(argumentName) /** - * The declaration couldn't be found for some reason, time to move on. We warn the user it needs to be rewritten - * by themselves. + * The declaration couldn't be found for some reason, time to move on. We + * warn the user it needs to be rewritten by themselves. */ if (!scope) { return undefined @@ -52,7 +51,7 @@ module.exports = ({ jscodeshift, utils }) => { /** * @param {import('jscodeshift').VariableDeclarator} binding - * @returns {import('jscodeshift').Node|undefined} + * @returns {import('jscodeshift').Node | undefined} */ const getInitializerByDeclarator = (binding) => { const isVariableDeclaration = jscodeshift.match(binding, { @@ -85,9 +84,9 @@ module.exports = ({ jscodeshift, utils }) => { /** * @param {import('jscodeshift').NodePath} path * @param {import('jscodeshift').Node} node - * @param {"queryKey"|"mutationKey"} keyName + * @param {'queryKey' | 'mutationKey'} keyName * @param {string} filePath - * @returns {import('jscodeshift').Property|undefined} + * @returns {import('jscodeshift').Property | undefined} */ const transformArgumentToKey = (path, node, keyName, filePath) => { // If the first argument is an identifier we have to infer its type if possible. diff --git a/packages/query-codemods/src/v5/remove-overloads/utils/unknown-usage-error.cjs b/packages/query-codemods/src/v5/remove-overloads/utils/unknown-usage-error.cjs index ff722ff1089..a1da2064bbf 100644 --- a/packages/query-codemods/src/v5/remove-overloads/utils/unknown-usage-error.cjs +++ b/packages/query-codemods/src/v5/remove-overloads/utils/unknown-usage-error.cjs @@ -10,7 +10,6 @@ class UnknownUsageError extends Error { } /** - * * @param {import('jscodeshift').CallExpression} callExpression * @param {string} filePath * @returns {string} diff --git a/packages/query-codemods/src/v5/rename-hydrate/rename-hydrate.cjs b/packages/query-codemods/src/v5/rename-hydrate/rename-hydrate.cjs index 488040d6a22..160474ecfd9 100644 --- a/packages/query-codemods/src/v5/rename-hydrate/rename-hydrate.cjs +++ b/packages/query-codemods/src/v5/rename-hydrate/rename-hydrate.cjs @@ -22,8 +22,9 @@ module.exports = (file, api) => { importSpecifiers.replaceWith(({ node: mutableNode }) => { /** - * When the local and imported names match which means the code doesn't contain import aliases, we need - * to replace only the import specifier. + * When the local and imported names match which means the code doesn't + * contain import aliases, we need to replace only the import specifier. + * * @type {boolean} */ const usesDefaultImport = diff --git a/packages/query-core/src/environmentManager.ts b/packages/query-core/src/environmentManager.ts index d535d48e3fd..425ff6ab772 100644 --- a/packages/query-core/src/environmentManager.ts +++ b/packages/query-core/src/environmentManager.ts @@ -1,40 +1,42 @@ import { isServer as defaultIsServer } from './utils' -/** - * A function that returns whether the code is running on the server. - */ +/** A function that returns whether the code is running on the server. */ export type IsServerValue = () => boolean let isServerFn: IsServerValue = () => defaultIsServer /** - * Returns whether the current runtime should be treated as a server environment. + * Returns whether the current runtime should be treated as a server + * environment. + * * @returns `true` if the runtime is treated as a server. */ export const isServer = (): boolean => isServerFn() /** - * Manages how TanStack Query detects whether the current runtime should be treated as - * server-side, which disables scheduling refetch timers and changes the default `retry` count - * and `gcTime`. By default, the detection treats a missing `window` (or the presence of a - * `Deno` global) as server. + * Manages how TanStack Query detects whether the current runtime should be + * treated as server-side, which disables scheduling refetch timers and changes + * the default `retry` count and `gcTime`. By default, the detection treats a + * missing `window` (or the presence of a `Deno` global) as server. + * + * Override this for runtimes where that default detection would give the wrong + * answer — for example, a Service Worker, where `window` is undefined even + * though the environment should behave like a client. * - * Override this for runtimes where that default detection would give the wrong answer — for - * example, a Service Worker, where `window` is undefined even though the environment should - * behave like a client. * @example - * ```ts - * import { environmentManager } from '@tanstack/query-core' + * ```ts + * import { environmentManager } from '@tanstack/query-core' * - * environmentManager.setIsServer(() => false) - * ``` + * environmentManager.setIsServer(() => false) + * ``` */ export const environmentManager = { isServer, /** * Overrides the server check globally. - * @param isServerValue - A function that returns whether the runtime should be treated as a - * server. + * + * @param isServerValue - A function that returns whether the runtime should + * be treated as a server. */ setIsServer(isServerValue: IsServerValue): void { isServerFn = isServerValue diff --git a/packages/query-core/src/focusManager.ts b/packages/query-core/src/focusManager.ts index 0dd0c9e8d1a..cd7c80942ac 100644 --- a/packages/query-core/src/focusManager.ts +++ b/packages/query-core/src/focusManager.ts @@ -9,7 +9,8 @@ type SetupFn = ( /** * The `FocusManager` manages the focus state within TanStack Query. * - * It can be used to change the default event listeners or to manually change the focus state. + * It can be used to change the default event listeners or to manually change + * the focus state. */ export class FocusManager extends Subscribable { #focused?: boolean @@ -50,30 +51,33 @@ export class FocusManager extends Subscribable { } /** - * `setEventListener` can be used to set a custom event listener that will - * be used to determine the focus state. The provided `setup` function - * receives a `setFocused` callback: call it with a `boolean` to manually - * set the focus state, or with no arguments to re-evaluate the current - * focus state and notify subscribers. - * @param setup - Receives the `setFocused` callback, registers the event listener, and may return - * a cleanup function that is called when the listener is replaced or no longer needed. + * `setEventListener` can be used to set a custom event listener that will be + * used to determine the focus state. The provided `setup` function receives a + * `setFocused` callback: call it with a `boolean` to manually set the focus + * state, or with no arguments to re-evaluate the current focus state and + * notify subscribers. + * * @example - * ```ts - * import { focusManager } from '@tanstack/query-core' + * ```ts + * import { focusManager } from '@tanstack/query-core' + * + * focusManager.setEventListener((handleFocus) => { + * const listener = () => handleFocus() + * // Listen to visibilitychange + * if (typeof window !== 'undefined' && window.addEventListener) { + * window.addEventListener('visibilitychange', listener, false) + * } * - * focusManager.setEventListener((handleFocus) => { - * const listener = () => handleFocus() - * // Listen to visibilitychange - * if (typeof window !== 'undefined' && window.addEventListener) { - * window.addEventListener('visibilitychange', listener, false) - * } + * return () => { + * // Be sure to unsubscribe if a new handler is set + * window.removeEventListener('visibilitychange', listener) + * } + * }) + * ``` * - * return () => { - * // Be sure to unsubscribe if a new handler is set - * window.removeEventListener('visibilitychange', listener) - * } - * }) - * ``` + * @param setup - Receives the `setFocused` callback, registers the event + * listener, and may return a cleanup function that is called when the + * listener is replaced or no longer needed. */ setEventListener(setup: SetupFn): void { this.#setup = setup @@ -90,20 +94,23 @@ export class FocusManager extends Subscribable { /** * `setFocused` can be used to manually set the focus state. Set `undefined` * to fall back to the default focus check. - * @param focused - The focus state, or `undefined` to use the default focus check. + * * @example - * ```ts - * import { focusManager } from '@tanstack/query-core' + * ```ts + * import { focusManager } from '@tanstack/query-core' + * + * // Set focused + * focusManager.setFocused(true) * - * // Set focused - * focusManager.setFocused(true) + * // Set unfocused + * focusManager.setFocused(false) * - * // Set unfocused - * focusManager.setFocused(false) + * // Fallback to the default focus check + * focusManager.setFocused(undefined) + * ``` * - * // Fallback to the default focus check - * focusManager.setFocused(undefined) - * ``` + * @param focused - The focus state, or `undefined` to use the default focus + * check. */ setFocused(focused?: boolean): void { const changed = this.#focused !== focused @@ -113,9 +120,7 @@ export class FocusManager extends Subscribable { } } - /** - * `onFocus` notifies all subscribed listeners with the current focus state. - */ + /** `onFocus` notifies all subscribed listeners with the current focus state. */ onFocus(): void { const isFocused = this.isFocused() this.listeners.forEach((listener) => { @@ -125,7 +130,9 @@ export class FocusManager extends Subscribable { /** * `isFocused` can be used to get the current focus state. - * @returns The focus state set with `setFocused`, or otherwise whether the document is visible. + * + * @returns The focus state set with `setFocused`, or otherwise whether the + * document is visible. */ isFocused(): boolean { if (typeof this.#focused === 'boolean') { @@ -139,6 +146,7 @@ export class FocusManager extends Subscribable { } /** - * Singleton instance of {@link FocusManager}, used to manage and observe the focus state within TanStack Query. + * Singleton instance of {@link FocusManager}, used to manage and observe the + * focus state within TanStack Query. */ export const focusManager = new FocusManager() diff --git a/packages/query-core/src/hydration.ts b/packages/query-core/src/hydration.ts index 6f763d645ae..b9aeaa4fdeb 100644 --- a/packages/query-core/src/hydration.ts +++ b/packages/query-core/src/hydration.ts @@ -17,11 +17,12 @@ import type { Mutation, MutationState } from './mutation' type TransformerFn = (data: any) => any /** - * Reads the value of a promise synchronously if it has already resolved, e.g. a thenable that - * resolves within its `then` call. + * Reads the value of a promise synchronously if it has already resolved, e.g. a + * thenable that resolves within its `then` call. + * * @param promise - The promise to read. - * @returns An object with the resolved `data`, or `undefined` if the promise hasn't resolved - * synchronously (or resolved with `undefined`). + * @returns An object with the resolved `data`, or `undefined` if the promise + * hasn't resolved synchronously (or resolved with `undefined`). */ function tryResolveSync(promise: PromiseLike) { let data: unknown @@ -43,36 +44,60 @@ function tryResolveSync(promise: PromiseLike) { } /** - * Options for `dehydrate`, controlling which queries/mutations are included in the resulting `DehydratedState` and - * how their data/errors are transformed before being serialized (e.g. for embedding in server-rendered markup). + * Options for `dehydrate`, controlling which queries/mutations are included in + * the resulting `DehydratedState` and how their data/errors are transformed + * before being serialized (e.g. for embedding in server-rendered markup). */ export interface DehydrateOptions { - /** Transforms a query's `data` before it is dehydrated. Useful for non-JSON-serializable data. */ + /** + * Transforms a query's `data` before it is dehydrated. Useful for + * non-JSON-serializable data. + */ serializeData?: TransformerFn - /** Predicate to decide whether a given `Mutation` should be dehydrated. Defaults to `defaultShouldDehydrateMutation`. */ + /** + * Predicate to decide whether a given `Mutation` should be dehydrated. + * Defaults to `defaultShouldDehydrateMutation`. + */ shouldDehydrateMutation?: (mutation: Mutation) => boolean - /** Predicate to decide whether a given `Query` should be dehydrated. Defaults to `defaultShouldDehydrateQuery`. */ + /** + * Predicate to decide whether a given `Query` should be dehydrated. Defaults + * to `defaultShouldDehydrateQuery`. + */ shouldDehydrateQuery?: (query: Query) => boolean /** - * Predicate to decide whether a query's error should be redacted before dehydration. Errors are redacted - * (replaced with a generic `Error('redacted')`) unless this function is provided and returns `false` for the - * given error, in which case the original error is kept. + * Predicate to decide whether a query's error should be redacted before + * dehydration. Errors are redacted (replaced with a generic + * `Error('redacted')`) unless this function is provided and returns `false` + * for the given error, in which case the original error is kept. */ shouldRedactErrors?: (error: unknown) => boolean } /** - * Options for `hydrate`, controlling the default options applied to queries/mutations restored from a - * `DehydratedState`, and how to reverse any transformation applied by `DehydrateOptions.serializeData`. + * Options for `hydrate`, controlling the default options applied to + * queries/mutations restored from a `DehydratedState`, and how to reverse any + * transformation applied by `DehydrateOptions.serializeData`. */ export interface HydrateOptions { - /** Options applied to the queries and mutations restored from the dehydrated state. */ + /** + * Options applied to the queries and mutations restored from the dehydrated + * state. + */ defaultOptions?: { - /** Transforms a query's `data` after it is read from the dehydrated state, reversing `serializeData`. */ + /** + * Transforms a query's `data` after it is read from the dehydrated state, + * reversing `serializeData`. + */ deserializeData?: TransformerFn - /** Default options merged into every query restored from the dehydrated state. */ + /** + * Default options merged into every query restored from the dehydrated + * state. + */ queries?: QueryOptions - /** Default options merged into every mutation restored from the dehydrated state. */ + /** + * Default options merged into every mutation restored from the dehydrated + * state. + */ mutations?: MutationOptions } } @@ -95,25 +120,25 @@ interface DehydratedQuery { } /** - * A serializable snapshot of a `QueryClient`'s cache, as produced by `dehydrate` and consumed by `hydrate`. Typically - * transported from server to client (e.g. embedded in server-rendered markup) to seed the client's cache with data - * that has already been fetched, avoiding a redundant fetch on the client. + * A serializable snapshot of a `QueryClient`'s cache, as produced by + * `dehydrate` and consumed by `hydrate`. Typically transported from server to + * client (e.g. embedded in server-rendered markup) to seed the client's cache + * with data that has already been fetched, avoiding a redundant fetch on the + * client. */ export interface DehydratedState { - /** - * The dehydrated mutations, by default only the paused ones. - */ + /** The dehydrated mutations, by default only the paused ones. */ mutations: Array - /** - * The dehydrated queries, by default only the successful ones. - */ + /** The dehydrated queries, by default only the successful ones. */ queries: Array } // FUNCTIONS /** - * Dehydrates a single `Mutation` into a serializable snapshot of its key, state, scope, and meta. + * Dehydrates a single `Mutation` into a serializable snapshot of its key, + * state, scope, and meta. + * * @param mutation - The mutation to dehydrate. * @returns The dehydrated mutation. */ @@ -127,14 +152,16 @@ function dehydrateMutation(mutation: Mutation): DehydratedMutation { } /** - * Prepares the in-flight promise of a pending query for dehydration: applies `serializeData` to its - * result, and redacts its rejection error unless `shouldRedactErrors` returns `false` for it. + * Prepares the in-flight promise of a pending query for dehydration: applies + * `serializeData` to its result, and redacts its rejection error unless + * `shouldRedactErrors` returns `false` for it. + * * @param query - The pending query whose promise is dehydrated. * @param serializeData - Optional transform applied to the resolved data. - * @param shouldRedactErrors - Optional predicate; if it returns `false` for the rejection error, - * that - * error is kept as-is instead of being redacted. - * @returns The transformed promise, or `undefined` if the query has no in-flight promise. + * @param shouldRedactErrors - Optional predicate; if it returns `false` for the + * rejection error, that error is kept as-is instead of being redacted. + * @returns The transformed promise, or `undefined` if the query has no + * in-flight promise. */ function dehydratePromise( query: Query, @@ -165,14 +192,19 @@ function dehydratePromise( } /** - * Dehydrates a single `Query` into a serializable `DehydratedQuery` snapshot. Note that most query config (e.g. - * `queryFn`, `staleTime`) is not dehydrated but instead meant to be configured again when consuming the - * de/rehydrated data, typically with `useQuery` on the client. If the query is still `pending`, its in-flight - * promise is dehydrated too so it can be resumed on the other side instead of re-fetched. + * Dehydrates a single `Query` into a serializable `DehydratedQuery` snapshot. + * Note that most query config (e.g. `queryFn`, `staleTime`) is not dehydrated + * but instead meant to be configured again when consuming the de/rehydrated + * data, typically with `useQuery` on the client. If the query is still + * `pending`, its in-flight promise is dehydrated too so it can be resumed on + * the other side instead of re-fetched. + * * @param query - The query to dehydrate. - * @param serializeData - Optional transform applied to `query.state.data` before it is included in the snapshot. - * @param shouldRedactErrors - Optional predicate; if it returns `false` for the promise's rejection error, that - * error is kept as-is instead of being redacted. + * @param serializeData - Optional transform applied to `query.state.data` + * before it is included in the snapshot. + * @param shouldRedactErrors - Optional predicate; if it returns `false` for the + * promise's rejection error, that error is kept as-is instead of being + * redacted. * @returns The dehydrated query. */ export function dehydrateQuery( @@ -201,8 +233,10 @@ export function dehydrateQuery( } /** - * The default `shouldDehydrateMutation` predicate used by `dehydrate`. Only dehydrates mutations that are - * currently paused (e.g. paused by `networkMode` while offline). + * The default `shouldDehydrateMutation` predicate used by `dehydrate`. Only + * dehydrates mutations that are currently paused (e.g. paused by `networkMode` + * while offline). + * * @param mutation - The mutation to check. * @returns `true` if the mutation is paused. */ @@ -211,8 +245,9 @@ export function defaultShouldDehydrateMutation(mutation: Mutation) { } /** - * The default `shouldDehydrateQuery` predicate used by `dehydrate`. Only dehydrates queries whose status is - * `'success'`. + * The default `shouldDehydrateQuery` predicate used by `dehydrate`. Only + * dehydrates queries whose status is `'success'`. + * * @param query - The query to check. * @returns `true` if the query's status is `'success'`. */ @@ -221,26 +256,31 @@ export function defaultShouldDehydrateQuery(query: Query) { } /** - * Dehydrates a `QueryClient`'s cache (queries and mutations) into a plain, serializable `DehydratedState`, - * typically to embed in server-rendered markup and later restore into a client-side `QueryClient` via `hydrate`. - * Which queries/mutations are included, and how their data/errors are transformed, is controlled by `options`, - * falling back to the client's `dehydrate` default options, and finally to `defaultShouldDehydrateQuery` / + * Dehydrates a `QueryClient`'s cache (queries and mutations) into a plain, + * serializable `DehydratedState`, typically to embed in server-rendered markup + * and later restore into a client-side `QueryClient` via `hydrate`. Which + * queries/mutations are included, and how their data/errors are transformed, is + * controlled by `options`, falling back to the client's `dehydrate` default + * options, and finally to `defaultShouldDehydrateQuery` / * `defaultShouldDehydrateMutation`. - * @param client - The client whose cache is dehydrated. - * @param options - Controls which queries and mutations are included and how their data and errors - * are transformed. Each option falls back to the client's `defaultOptions.dehydrate`. - * @returns The dehydrated state, with the included `queries` and `mutations`. + * * @example - * ```ts - * const queryClient = new QueryClient() + * ```ts + * const queryClient = new QueryClient() * - * await queryClient.prefetchQuery({ - * queryKey: ['posts'], - * queryFn: getPosts, - * }) + * await queryClient.prefetchQuery({ + * queryKey: ['posts'], + * queryFn: getPosts, + * }) * - * const dehydratedState = dehydrate(queryClient) - * ``` + * const dehydratedState = dehydrate(queryClient) + * ``` + * + * @param client - The client whose cache is dehydrated. + * @param options - Controls which queries and mutations are included and how + * their data and errors are transformed. Each option falls back to the + * client's `defaultOptions.dehydrate`. + * @returns The dehydrated state, with the included `queries` and `mutations`. */ export function dehydrate( client: QueryClient, @@ -283,25 +323,32 @@ export function dehydrate( } /** - * Restores a `DehydratedState` (as produced by `dehydrate`) into a `QueryClient`'s cache, typically to seed the - * client with data already fetched on the server. `mutations` and `queries` are each optional on `dehydratedState`. - * Queries not yet in the cache are built from the dehydrated snapshot; queries that already exist are only updated - * when the dehydrated data is newer than what's already cached. Newly built queries have their `fetchStatus` reset - * to `'idle'` so they don't hydrate stuck in a fetching state. If a dehydrated query still had an in-flight - * promise, it is resumed via `query.fetch()` (reusing that promise as `initialPromise`) rather than re-invoking - * `queryFn`. - * @param client - The client whose cache is restored into. - * @param dehydratedState - The dehydrated state, e.g. produced by `dehydrate` on the server. - * @param options - `defaultOptions` merged into every restored query and mutation (on top of the - * client's `defaultOptions.hydrate`), and `deserializeData` to reverse `serializeData`. + * Restores a `DehydratedState` (as produced by `dehydrate`) into a + * `QueryClient`'s cache, typically to seed the client with data already fetched + * on the server. `mutations` and `queries` are each optional on + * `dehydratedState`. Queries not yet in the cache are built from the dehydrated + * snapshot; queries that already exist are only updated when the dehydrated + * data is newer than what's already cached. Newly built queries have their + * `fetchStatus` reset to `'idle'` so they don't hydrate stuck in a fetching + * state. If a dehydrated query still had an in-flight promise, it is resumed + * via `query.fetch()` (reusing that promise as `initialPromise`) rather than + * re-invoking `queryFn`. + * * @example - * ```ts - * // dehydratedState was produced by `dehydrate` on the server - * // and sent to the client, e.g. embedded in server-rendered markup. - * const queryClient = new QueryClient() + * ```ts + * // dehydratedState was produced by `dehydrate` on the server + * // and sent to the client, e.g. embedded in server-rendered markup. + * const queryClient = new QueryClient() + * + * hydrate(queryClient, dehydratedState) + * ``` * - * hydrate(queryClient, dehydratedState) - * ``` + * @param client - The client whose cache is restored into. + * @param dehydratedState - The dehydrated state, e.g. produced by `dehydrate` + * on the server. + * @param options - `defaultOptions` merged into every restored query and + * mutation (on top of the client's `defaultOptions.hydrate`), and + * `deserializeData` to reverse `serializeData`. */ export function hydrate( client: QueryClient, diff --git a/packages/query-core/src/infiniteQueryBehavior.ts b/packages/query-core/src/infiniteQueryBehavior.ts index 38422a3380e..062c0e51cc4 100644 --- a/packages/query-core/src/infiniteQueryBehavior.ts +++ b/packages/query-core/src/infiniteQueryBehavior.ts @@ -14,11 +14,13 @@ import type { } from './types' /** - * Creates the behavior that fetches the pages of an infinite query: the next or previous page for - * `fetchNextPage`/`fetchPreviousPage`, or all pages again from the start on a refetch. - * @param pages - The number of pages to fetch from the start when all pages are fetched again, - * e.g. from the `pages` option of `queryClient.infiniteQuery`. Defaults to the number of cached - * pages. + * Creates the behavior that fetches the pages of an infinite query: the next or + * previous page for `fetchNextPage`/`fetchPreviousPage`, or all pages again + * from the start on a refetch. + * + * @param pages - The number of pages to fetch from the start when all pages are + * fetched again, e.g. from the `pages` option of `queryClient.infiniteQuery`. + * Defaults to the number of cached pages. * @returns The query behavior to set on an infinite query. */ export function infiniteQueryBehavior( @@ -140,7 +142,9 @@ export function infiniteQueryBehavior( } /** - * Computes the page param of the page after the last one, with the `getNextPageParam` option. + * Computes the page param of the page after the last one, with the + * `getNextPageParam` option. + * * @param options - The infinite query options. * @param data - The current pages and page params. * @returns The next page param, or `undefined` if there are no pages yet. @@ -161,12 +165,13 @@ function getNextPageParam( } /** - * Computes the page param of the page before the first one, with the `getPreviousPageParam` - * option. + * Computes the page param of the page before the first one, with the + * `getPreviousPageParam` option. + * * @param options - The infinite query options. * @param data - The current pages and page params. - * @returns The previous page param, or `undefined` if there are no pages yet or no - * `getPreviousPageParam` option. + * @returns The previous page param, or `undefined` if there are no pages yet or + * no `getPreviousPageParam` option. */ function getPreviousPageParam( options: InfiniteQueryPageParamsOptions, @@ -179,9 +184,11 @@ function getPreviousPageParam( /** * Checks if there is a next page. + * * @param options - The infinite query options with `getNextPageParam`. * @param data - The current pages and page params. - * @returns `true` if `getNextPageParam` returns a value other than `null` or `undefined`. + * @returns `true` if `getNextPageParam` returns a value other than `null` or + * `undefined`. */ export function hasNextPage( options: InfiniteQueryPageParamsOptions, @@ -193,10 +200,11 @@ export function hasNextPage( /** * Checks if there is a previous page. + * * @param options - The infinite query options with `getPreviousPageParam`. * @param data - The current pages and page params. - * @returns `true` if `getPreviousPageParam` is set and returns a value other than `null` or - * `undefined`. + * @returns `true` if `getPreviousPageParam` is set and returns a value other + * than `null` or `undefined`. */ export function hasPreviousPage( options: InfiniteQueryPageParamsOptions, diff --git a/packages/query-core/src/infiniteQueryObserver.ts b/packages/query-core/src/infiniteQueryObserver.ts index e5005a06c45..249a4d8fed6 100644 --- a/packages/query-core/src/infiniteQueryObserver.ts +++ b/packages/query-core/src/infiniteQueryObserver.ts @@ -25,17 +25,18 @@ type InfiniteQueryObserverListener = ( * infinite-query-specific fields and methods, such as `hasNextPage` and * `fetchNextPage`, and is the primitive that framework adapters (e.g. * `useInfiniteQuery`) build their hooks on top of. + * * @example - * ```ts - * const observer = new InfiniteQueryObserver(queryClient, { - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextCursor, - * }) + * ```ts + * const observer = new InfiniteQueryObserver(queryClient, { + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextCursor, + * }) * - * const unsubscribe = observer.subscribe((result) => console.log(result)) - * ``` + * const unsubscribe = observer.subscribe((result) => console.log(result)) + * ``` */ export class InfiniteQueryObserver< TQueryFnData = unknown, @@ -100,9 +101,9 @@ export class InfiniteQueryObserver< /** * Updates the observer's options. Behaves the same as - * `QueryObserver.setOptions`, additionally marking the options as - * belonging to an infinite query before delegating to the base - * implementation. + * `QueryObserver.setOptions`, additionally marking the options as belonging + * to an infinite query before delegating to the base implementation. + * * @param options - The new infinite query observer options. */ override setOptions( @@ -119,11 +120,13 @@ export class InfiniteQueryObserver< } /** - * The infinite-query counterpart of {@link QueryObserver#getOptimisticResult}, marking the - * options as an infinite query before delegating to it. Called by framework adapters (e.g. - * `useInfiniteQuery`) ahead of subscribing, to compute the current `InfiniteQueryObserverResult` - * synchronously. - * @param options - The defaulted infinite query observer options to compute the result for. + * The infinite-query counterpart of {@link QueryObserver#getOptimisticResult}, + * marking the options as an infinite query before delegating to it. Called by + * framework adapters (e.g. `useInfiniteQuery`) ahead of subscribing, to + * compute the current `InfiniteQueryObserverResult` synchronously. + * + * @param options - The defaulted infinite query observer options to compute + * the result for. * @returns The result for the given options. */ override getOptimisticResult( @@ -144,23 +147,26 @@ export class InfiniteQueryObserver< /** * Fetches the next page of the infinite query and returns a promise that - * resolves with the resulting `InfiniteQueryObserverResult`. The page - * param used for the fetch is determined by `getNextPageParam`, which - * receives the current pages/page params and whose result also determines - * `hasNextPage`. - * @param options - Set `cancelRefetch` to `false` to ignore the call while a fetch is running, - * and `throwOnError` to `true` to reject when the fetch fails. - * @returns A promise that resolves with the result after the next page is fetched. With - * `cancelRefetch: false`, a running fetch is reused instead, so the next page may not be fetched. - * @see {@link InfiniteQueryObserver#fetchPreviousPage} + * resolves with the resulting `InfiniteQueryObserverResult`. The page param + * used for the fetch is determined by `getNextPageParam`, which receives the + * current pages/page params and whose result also determines `hasNextPage`. + * * @example - * ```ts - * const { hasNextPage } = observer.getCurrentResult() + * ```ts + * const { hasNextPage } = observer.getCurrentResult() + * + * if (hasNextPage) { + * await observer.fetchNextPage() + * } + * ``` * - * if (hasNextPage) { - * await observer.fetchNextPage() - * } - * ``` + * @param options - Set `cancelRefetch` to `false` to ignore the call while a + * fetch is running, and `throwOnError` to `true` to reject when the fetch + * fails. + * @returns A promise that resolves with the result after the next page is + * fetched. With `cancelRefetch: false`, a running fetch is reused instead, + * so the next page may not be fetched. + * @see {@link InfiniteQueryObserver#fetchPreviousPage} */ fetchNextPage( options?: FetchNextPageOptions, @@ -174,24 +180,28 @@ export class InfiniteQueryObserver< } /** - * Fetches the previous page of the infinite query and returns a promise - * that resolves with the resulting `InfiniteQueryObserverResult`. The page - * param used for the fetch is determined by `getPreviousPageParam`, which - * receives the current pages/page params and whose result also determines + * Fetches the previous page of the infinite query and returns a promise that + * resolves with the resulting `InfiniteQueryObserverResult`. The page param + * used for the fetch is determined by `getPreviousPageParam`, which receives + * the current pages/page params and whose result also determines * `hasPreviousPage`. - * @param options - Set `cancelRefetch` to `false` to ignore the call while a fetch is running, - * and `throwOnError` to `true` to reject when the fetch fails. - * @returns A promise that resolves with the result after the previous page is fetched. With - * `cancelRefetch: false`, a running fetch is reused instead, so the previous page may not be fetched. - * @see {@link InfiniteQueryObserver#fetchNextPage} + * * @example - * ```ts - * const { hasPreviousPage } = observer.getCurrentResult() + * ```ts + * const { hasPreviousPage } = observer.getCurrentResult() * - * if (hasPreviousPage) { - * await observer.fetchPreviousPage() - * } - * ``` + * if (hasPreviousPage) { + * await observer.fetchPreviousPage() + * } + * ``` + * + * @param options - Set `cancelRefetch` to `false` to ignore the call while a + * fetch is running, and `throwOnError` to `true` to reject when the fetch + * fails. + * @returns A promise that resolves with the result after the previous page is + * fetched. With `cancelRefetch: false`, a running fetch is reused instead, + * so the previous page may not be fetched. + * @see {@link InfiniteQueryObserver#fetchNextPage} */ fetchPreviousPage( options?: FetchPreviousPageOptions, diff --git a/packages/query-core/src/mutation.ts b/packages/query-core/src/mutation.ts index d7263f01467..82fa49aef53 100644 --- a/packages/query-core/src/mutation.ts +++ b/packages/query-core/src/mutation.ts @@ -38,39 +38,32 @@ export interface MutationState< * `onError` and `onSettled` as the mutation's context. */ context: TOnMutateResult | undefined - /** - * The last successfully resolved data for the mutation. - */ + /** The last successfully resolved data for the mutation. */ data: TData | undefined /** - * The error object for the mutation, if the last attempt resulted in an error. + * The error object for the mutation, if the last attempt resulted in an + * error. + * * - Defaults to `null`. */ error: TError | null /** - * The number of times the mutation function has failed for the current attempt. + * The number of times the mutation function has failed for the current + * attempt. */ failureCount: number - /** - * The reason the current attempt failed, as reported by the retryer. - */ + /** The reason the current attempt failed, as reported by the retryer. */ failureReason: TError | null /** - * Whether the mutation is currently paused (see network mode), or is - * waiting for another mutation with the same `scope` to finish. + * Whether the mutation is currently paused (see network mode), or is waiting + * for another mutation with the same `scope` to finish. */ isPaused: boolean - /** - * The status of the mutation. - */ + /** The status of the mutation. */ status: MutationStatus - /** - * The variables the mutation was last called with. - */ + /** The variables the mutation was last called with. */ variables: TVariables | undefined - /** - * The timestamp for when the mutation was submitted. - */ + /** The timestamp for when the mutation was submitted. */ submittedAt: number } @@ -106,8 +99,8 @@ interface ContinueAction { } /** - * The actions a mutation dispatches to update its state, e.g. when it starts, fails, pauses, or - * succeeds. + * The actions a mutation dispatches to update its state, e.g. when it starts, + * fails, pauses, or succeeds. */ export type Action = | ContinueAction @@ -125,15 +118,16 @@ export type Action = * subscribed to it. * * Instances are created and managed internally by `MutationCache`; application - * code typically interacts with mutations indirectly through `QueryClient` or - * a framework hook like `useMutation`. Direct access to a `Mutation` instance - * is possible via `mutationCache.find()`/`getAll()` for inspecting cache state. + * code typically interacts with mutations indirectly through `QueryClient` or a + * framework hook like `useMutation`. Direct access to a `Mutation` instance is + * possible via `mutationCache.find()`/`getAll()` for inspecting cache state. + * * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() + * ```ts + * const mutationCache = queryClient.getMutationCache() * - * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) - * ``` + * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) + * ``` */ export class Mutation< TData = unknown, @@ -169,8 +163,9 @@ export class Mutation< /** * Replaces the mutation's options and applies their `gcTime`. - * @internal + * * @param options - The new mutation options. + * @internal */ setOptions( options: MutationOptions, @@ -182,6 +177,7 @@ export class Mutation< /** * The `meta` object passed in the mutation's options, if any. + * * @returns The mutation's `meta`, or `undefined` if none was set. */ get meta(): MutationMeta | undefined { @@ -190,9 +186,10 @@ export class Mutation< /** * Subscribes an observer to the mutation and stops its garbage collection. + * + * @param observer - The observer to add. Adding an observer that is already + * subscribed does nothing. * @internal - * @param observer - The observer to add. Adding an observer that is already subscribed does - * nothing. */ addObserver(observer: MutationObserver): void { if (!this.#observers.includes(observer)) { @@ -211,8 +208,10 @@ export class Mutation< /** * Unsubscribes an observer from the mutation. + * + * @param observer - The observer to remove. Garbage collection is scheduled + * afterwards. * @internal - * @param observer - The observer to remove. Garbage collection is scheduled afterwards. */ removeObserver(observer: MutationObserver): void { this.#observers = this.#observers.filter((x) => x !== observer) @@ -240,22 +239,25 @@ export class Mutation< * Resumes a mutation that is currently paused or was restored from a * dehydrated, still-`pending` state. * - * - If this mutation has an active retryer (it paused mid-attempt, e.g. due - * to the network mode or scope-based queuing), its retryer is resumed. + * - If this mutation has an active retryer (it paused mid-attempt, e.g. due to + * the network mode or scope-based queuing), its retryer is resumed. * - Otherwise, if the mutation's status is still `pending` (e.g. it was - * dehydrated while an attempt was in flight and never got a retryer in - * this instance), `execute` is called again with the last known variables. + * dehydrated while an attempt was in flight and never got a retryer in this + * instance), `execute` is called again with the last known variables. * - Otherwise the mutation has already settled and this resolves immediately * without running anything again. - * @returns A promise that settles with the resumed mutation: it rejects if the mutation fails. - * It resolves immediately if the mutation has already settled. - * @see {@link Mutation#execute} + * * @example - * ```ts - * // typically driven by reconnect handling, e.g. queryClient.resumePausedMutations() - * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) - * await mutation?.continue() - * ``` + * ```ts + * // typically driven by reconnect handling, e.g. queryClient.resumePausedMutations() + * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) + * await mutation?.continue() + * ``` + * + * @returns A promise that settles with the resumed mutation: it rejects if + * the mutation fails. It resolves immediately if the mutation has already + * settled. + * @see {@link Mutation#execute} */ continue(): Promise { return ( @@ -274,29 +276,32 @@ export class Mutation< * * If this mutation's state is already `pending` when `execute` is called * (i.e. it was restored, still in-flight, from a dehydrated state), the - * `onMutate` step is skipped and a `continue` action is dispatched to - * unpause it; otherwise a `pending` action is dispatched first, then the - * mutation cache's `onMutate` and the mutation's own `onMutate` option are - * awaited in that order, and the resulting context is stored. + * `onMutate` step is skipped and a `continue` action is dispatched to unpause + * it; otherwise a `pending` action is dispatched first, then the mutation + * cache's `onMutate` and the mutation's own `onMutate` option are awaited in + * that order, and the resulting context is stored. * * The mutation function is then run (subject to `retry`/`retryDelay`/ - * `networkMode`, and to the mutation cache's scope-based serialization). - * On success, the cache's `onSuccess`/`onSettled` callbacks run before the + * `networkMode`, and to the mutation cache's scope-based serialization). On + * success, the cache's `onSuccess`/`onSettled` callbacks run before the * mutation's own `onSuccess`/`onSettled` options, a `success` action is * dispatched, and the resolved data is returned. On failure, the same * cache-then-option ordering is used for `onError`/`onSettled`, but each of * those four callbacks is individually caught so that a throwing callback * cannot mask the original error; an `error` action is then dispatched and * the original error is re-thrown. + * + * @example + * ```ts + * // Called internally by `MutationObserver.mutate` and `Mutation.continue` — + * // applications normally trigger mutations through those, not this method. + * const data = await mutation.execute(variables) + * ``` + * * @param variables - The variables passed to the `mutationFn`. - * @returns A promise that resolves with the mutation's data, or rejects with its error. + * @returns A promise that resolves with the mutation's data, or rejects with + * its error. * @see {@link Mutation#continue} - * @example - * ```ts - * // Called internally by `MutationObserver.mutate` and `Mutation.continue` — - * // applications normally trigger mutations through those, not this method. - * const data = await mutation.execute(variables) - * ``` */ async execute(variables: TVariables): Promise { const onContinue = () => { @@ -533,7 +538,9 @@ export class Mutation< } /** - * Returns the initial state of a mutation: `'idle'`, with no data, error, or variables. + * Returns the initial state of a mutation: `'idle'`, with no data, error, or + * variables. + * * @returns The initial mutation state. */ export function getDefaultState< diff --git a/packages/query-core/src/mutationCache.ts b/packages/query-core/src/mutationCache.ts index d709fe154f4..6013d6f4555 100644 --- a/packages/query-core/src/mutationCache.ts +++ b/packages/query-core/src/mutationCache.ts @@ -16,12 +16,14 @@ import type { MutationFilters } from './utils' // TYPES /** - * Global callbacks that fire for every mutation handled by a `MutationCache`, regardless of which - * component or observer triggered it. They differ from the `defaultOptions` provided to a - * `QueryClient` in two ways: `defaultOptions` can be overridden by each mutation, while these - * callbacks are always called, and `onMutate` here does not allow returning a result. + * Global callbacks that fire for every mutation handled by a `MutationCache`, + * regardless of which component or observer triggered it. They differ from the + * `defaultOptions` provided to a `QueryClient` in two ways: `defaultOptions` + * can be overridden by each mutation, while these callbacks are always called, + * and `onMutate` here does not allow returning a result. * - * If a callback returns a promise, it will be awaited before the mutation continues. + * If a callback returns a promise, it will be awaited before the mutation + * continues. */ export interface MutationCacheConfig { /** Called when any mutation in the cache encounters an error. */ @@ -46,7 +48,10 @@ export interface MutationCacheConfig { mutation: Mutation, context: MutationFunctionContext, ) => Promise | unknown - /** Called when any mutation in the cache is settled, either successfully or with an error. */ + /** + * Called when any mutation in the cache is settled, either successfully or + * with an error. + */ onSettled?: ( data: unknown | undefined, error: DefaultError | null, @@ -91,9 +96,9 @@ interface NotifyEventMutationUpdated extends NotifyEvent { } /** - * The event passed to a `MutationCache` subscriber. Fired whenever a mutation is added or removed - * from the cache, its state is updated, or one of its observers is added, removed, or has its - * options updated. + * The event passed to a `MutationCache` subscriber. Fired whenever a mutation + * is added or removed from the cache, its state is updated, or one of its + * observers is added, removed, or has its options updated. */ export type MutationCacheNotifyEvent = | NotifyEventMutationAdded @@ -110,15 +115,17 @@ type MutationCacheListener = (event: MutationCacheNotifyEvent) => void /** * The `MutationCache` is the storage for mutations. * - * Normally, you will not interact with the `MutationCache` directly and instead use a - * `QueryClient`. You can subscribe to it (inherited from `Subscribable`) to be informed of - * safe/known updates to the cache, such as mutations being added, removed, or updated. + * Normally, you will not interact with the `MutationCache` directly and instead + * use a `QueryClient`. You can subscribe to it (inherited from `Subscribable`) + * to be informed of safe/known updates to the cache, such as mutations being + * added, removed, or updated. + * * @example - * ```ts - * const unsubscribe = mutationCache.subscribe((event) => { - * console.log(event.type, event.mutation) - * }) - * ``` + * ```ts + * const unsubscribe = mutationCache.subscribe((event) => { + * console.log(event.type, event.mutation) + * }) + * ``` */ export class MutationCache extends Subscribable { #mutations: Set> @@ -134,12 +141,16 @@ export class MutationCache extends Subscribable { /** * Creates a mutation and adds it to the cache. - * @internal - * @param client - The client the mutation belongs to, used to default its options. - * @param options - The mutation options. They are defaulted with {@link - * QueryClient#defaultMutationOptions}. - * @param state - The initial state of the mutation, e.g. when restoring a dehydrated mutation. + * + * @param client - The client the mutation belongs to, used to default its + * options. + * @param options - The mutation options. They are defaulted with + * {@link + * QueryClient#defaultMutationOptions}. + * @param state - The initial state of the mutation, e.g. when restoring a + * dehydrated mutation. * @returns The new mutation, already added to the cache. + * @internal */ build( client: QueryClient, @@ -161,8 +172,10 @@ export class MutationCache extends Subscribable { /** * Adds a mutation to the cache. + * + * @param mutation - The mutation to add. If it has a `scope`, it is queued in + * that scope. * @internal - * @param mutation - The mutation to add. If it has a `scope`, it is queued in that scope. */ add(mutation: Mutation): void { this.#mutations.add(mutation) @@ -180,8 +193,9 @@ export class MutationCache extends Subscribable { /** * Removes a mutation from the cache. - * @internal + * * @param mutation - The mutation to remove, also from its scope's queue. + * @internal */ remove(mutation: Mutation): void { if (this.#mutations.delete(mutation)) { @@ -207,11 +221,13 @@ export class MutationCache extends Subscribable { } /** - * Checks whether a mutation can run now, given the other mutations in its `scope`. - * @internal + * Checks whether a mutation can run now, given the other mutations in its + * `scope`. + * * @param mutation - The mutation to check. - * @returns `true` if the mutation has no `scope`, or no other mutation in its scope is pending - * ahead of it. + * @returns `true` if the mutation has no `scope`, or no other mutation in its + * scope is pending ahead of it. + * @internal */ canRun(mutation: Mutation): boolean { const scope = scopeFor(mutation) @@ -231,11 +247,13 @@ export class MutationCache extends Subscribable { } /** - * Continues the next paused mutation in the same `scope` after a mutation finishes. - * @internal + * Continues the next paused mutation in the same `scope` after a mutation + * finishes. + * * @param mutation - The mutation that finished. - * @returns A promise that resolves once the next paused mutation in the same scope has continued, - * or immediately if there is none. + * @returns A promise that resolves once the next paused mutation in the same + * scope has continued, or immediately if there is none. + * @internal */ runNext(mutation: Mutation): Promise { const scope = scopeFor(mutation) @@ -252,12 +270,13 @@ export class MutationCache extends Subscribable { /** * Removes all mutations from the cache. + * * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() + * ```ts + * const mutationCache = queryClient.getMutationCache() * - * mutationCache.clear() - * ``` + * mutationCache.clear() + * ``` */ clear(): void { notifyManager.batch(() => { @@ -273,35 +292,40 @@ export class MutationCache extends Subscribable { /** * Returns all mutations within the cache. * - * This is not typically needed for most applications, but can come in handy when needing more - * information about a mutation in rare scenarios. - * @returns Every mutation in the cache. + * This is not typically needed for most applications, but can come in handy + * when needing more information about a mutation in rare scenarios. + * * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() + * ```ts + * const mutationCache = queryClient.getMutationCache() * - * const mutations = mutationCache.getAll() - * ``` + * const mutations = mutationCache.getAll() + * ``` + * + * @returns Every mutation in the cache. */ getAll(): Array { return Array.from(this.#mutations) } /** - * A slightly more advanced method that can be used to get an existing mutation instance from - * the cache. If the mutation does not exist, `undefined` is returned. + * A slightly more advanced method that can be used to get an existing + * mutation instance from the cache. If the mutation does not exist, + * `undefined` is returned. + * + * This is not typically needed for most applications, but can come in handy + * when needing more information about a mutation in rare scenarios. + * + * @example + * ```ts + * const mutationCache = queryClient.getMutationCache() + * + * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) + * ``` * - * This is not typically needed for most applications, but can come in handy when needing more - * information about a mutation in rare scenarios. * @param filters - The filters to match. `exact` defaults to `true`. * @returns The first matching mutation, or `undefined`. * @see {@link MutationCache#findAll} - * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() - * - * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) - * ``` */ find< TData = unknown, @@ -319,20 +343,24 @@ export class MutationCache extends Subscribable { } /** - * An even more advanced method that can be used to get existing mutation instances from the - * cache that match the given filters. If no mutations match, an empty array is returned. + * An even more advanced method that can be used to get existing mutation + * instances from the cache that match the given filters. If no mutations + * match, an empty array is returned. + * + * This is not typically needed for most applications, but can come in handy + * when needing more information about mutations in rare scenarios. * - * This is not typically needed for most applications, but can come in handy when needing more - * information about mutations in rare scenarios. - * @param filters - The filters to match. Without filters, every mutation is returned. - * @returns The matching mutations. - * @see {@link MutationCache#find} * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() + * ```ts + * const mutationCache = queryClient.getMutationCache() + * + * const mutations = mutationCache.findAll({ mutationKey: ['addPost'] }) + * ``` * - * const mutations = mutationCache.findAll({ mutationKey: ['addPost'] }) - * ``` + * @param filters - The filters to match. Without filters, every mutation is + * returned. + * @returns The matching mutations. + * @see {@link MutationCache#find} */ findAll(filters: MutationFilters = {}): Array { return this.getAll().filter((mutation) => matchMutation(filters, mutation)) @@ -340,8 +368,9 @@ export class MutationCache extends Subscribable { /** * Notifies every cache listener of an event, in one batch. - * @internal + * * @param event - The event passed to every listener. + * @internal */ notify(event: MutationCacheNotifyEvent) { notifyManager.batch(() => { @@ -353,8 +382,10 @@ export class MutationCache extends Subscribable { /** * Continues every paused mutation, e.g. when the app comes back online. + * + * @returns A promise that resolves once every paused mutation has continued + * and settled. * @internal - * @returns A promise that resolves once every paused mutation has continued and settled. */ resumePausedMutations(): Promise { const pausedMutations = this.getAll().filter((x) => x.state.isPaused) @@ -368,7 +399,9 @@ export class MutationCache extends Subscribable { } /** - * Returns the scope id of a mutation, used to run mutations with the same scope one after another. + * Returns the scope id of a mutation, used to run mutations with the same scope + * one after another. + * * @param mutation - The mutation to read the scope of. * @returns The mutation's `scope.id`, or `undefined` if it has no scope. */ diff --git a/packages/query-core/src/mutationObserver.ts b/packages/query-core/src/mutationObserver.ts index f8f0fc560aa..7c8265877ca 100644 --- a/packages/query-core/src/mutationObserver.ts +++ b/packages/query-core/src/mutationObserver.ts @@ -21,18 +21,19 @@ type MutationObserverListener = ( // CLASS /** - * Observes a single mutation and derives a `MutationObserverResult` from it. - * A framework hook like `useMutation` creates one `MutationObserver` per hook + * Observes a single mutation and derives a `MutationObserverResult` from it. A + * framework hook like `useMutation` creates one `MutationObserver` per hook * call, keeps it stable across re-renders, calls `setOptions` when the options * passed to the hook change, subscribes to it to re-render on updates, and - * reads `getCurrentResult()` for the value to return. Calling `mutate()` - * builds a new underlying `Mutation` in the `MutationCache` and executes it. + * reads `getCurrentResult()` for the value to return. Calling `mutate()` builds + * a new underlying `Mutation` in the `MutationCache` and executes it. + * * @example - * ```ts - * const observer = new MutationObserver(queryClient, { - * mutationFn: (variables: { title: string }) => addPost(variables), - * }) - * ``` + * ```ts + * const observer = new MutationObserver(queryClient, { + * mutationFn: (variables: { title: string }) => addPost(variables), + * }) + * ``` */ export class MutationObserver< TData = unknown, @@ -72,8 +73,8 @@ export class MutationObserver< } /** - * Binds the methods of the result (`mutate` and `reset`) to the observer, so they keep working when - * destructured from it. + * Binds the methods of the result (`mutate` and `reset`) to the observer, so + * they keep working when destructured from it. */ protected bindMethods(): void { this.mutate = this.mutate.bind(this) @@ -87,15 +88,18 @@ export class MutationObserver< * defined), the observer is reset, detaching it from the mutation it was * observing. Otherwise, if the currently observed mutation is still * `pending`, its options are updated in place as well. - * @param options - The new mutation observer options. They are defaulted with {@link - * QueryClient#defaultMutationOptions} before being applied. + * * @example - * ```ts - * observer.setOptions({ - * mutationFn: (variables: { title: string }) => addPost(variables), - * onSuccess: (data) => console.log(data), - * }) - * ``` + * ```ts + * observer.setOptions({ + * mutationFn: (variables: { title: string }) => addPost(variables), + * onSuccess: (data) => console.log(data), + * }) + * ``` + * + * @param options - The new mutation observer options. They are defaulted with + * {@link + * QueryClient#defaultMutationOptions} before being applied. */ setOptions( options: MutationObserverOptions< @@ -143,10 +147,12 @@ export class MutationObserver< } /** - * Updates the observer's result when the observed mutation changes, and notifies its listeners. + * Updates the observer's result when the observed mutation changes, and + * notifies its listeners. + * + * @param action - The action that updated the observed mutation, passed on to + * the observer's callbacks. * @internal - * @param action - The action that updated the observed mutation, passed on to the observer's - * callbacks. */ onMutationUpdate( action: Action, @@ -157,9 +163,10 @@ export class MutationObserver< } /** - * Returns the observer's current result, derived from the observed - * mutation's state (or the default, `idle` state if no mutation has been - * built yet, e.g. before the first `mutate()` call or after `reset()`). + * Returns the observer's current result, derived from the observed mutation's + * state (or the default, `idle` state if no mutation has been built yet, e.g. + * before the first `mutate()` call or after `reset()`). + * * @returns The observer's latest result. */ getCurrentResult(): MutationObserverResult< @@ -172,18 +179,20 @@ export class MutationObserver< } /** - * Detaches the observer from the mutation it is currently observing (if - * any) and resets the observed result back to its default, `idle` state. + * Detaches the observer from the mutation it is currently observing (if any) + * and resets the observed result back to its default, `idle` state. * * This does not cancel an in-flight mutation; the mutation itself keeps - * running to completion and its own callbacks still fire, but this - * observer stops reflecting its state and a subsequent `mutate()` call - * will build a brand new mutation. - * @see {@link MutationObserver#mutate} + * running to completion and its own callbacks still fire, but this observer + * stops reflecting its state and a subsequent `mutate()` call will build a + * brand new mutation. + * * @example - * ```ts - * observer.reset() - * ``` + * ```ts + * observer.reset() + * ``` + * + * @see {@link MutationObserver#mutate} */ reset(): void { // reset needs to remove the observer from the mutation because there is no way to "get it back" @@ -195,24 +204,27 @@ export class MutationObserver< } /** - * Builds a new `Mutation` in the `MutationCache` using the observer's - * current options, detaches this observer from any previously observed - * mutation, attaches it to the new one, and executes it with the given - * variables. + * Builds a new `Mutation` in the `MutationCache` using the observer's current + * options, detaches this observer from any previously observed mutation, + * attaches it to the new one, and executes it with the given variables. * * The optional per-call `options` (`onSuccess`/`onError`/`onSettled`) are - * invoked once the mutation settles, in addition to any callbacks defined - * on the observer's own options. - * @param variables - The variables passed to the `mutationFn`. - * @param options - Per-call `onSuccess`, `onError`, and `onSettled` callbacks. - * @returns A promise that resolves with the mutation's data, or rejects with its error. + * invoked once the mutation settles, in addition to any callbacks defined on + * the observer's own options. + * * @example - * ```ts - * await observer.mutate( - * { title: 'New post' }, - * { onSuccess: (data) => console.log(data) }, - * ) - * ``` + * ```ts + * await observer.mutate( + * { title: 'New post' }, + * { onSuccess: (data) => console.log(data) }, + * ) + * ``` + * + * @param variables - The variables passed to the `mutationFn`. + * @param options - Per-call `onSuccess`, `onError`, and `onSettled` + * callbacks. + * @returns A promise that resolves with the mutation's data, or rejects with + * its error. */ mutate( variables: TVariables, diff --git a/packages/query-core/src/notifyManager.ts b/packages/query-core/src/notifyManager.ts index ffd507f8854..2a9843f03ca 100644 --- a/packages/query-core/src/notifyManager.ts +++ b/packages/query-core/src/notifyManager.ts @@ -13,14 +13,16 @@ type BatchCallsCallback> = (...args: T) => void type ScheduleFunction = (callback: () => void) => void /** - * Default scheduling function used by the notify manager. - * Schedules the callback with the system's `setTimeout(callback, 0)`. + * Default scheduling function used by the notify manager. Schedules the + * callback with the system's `setTimeout(callback, 0)`. */ export const defaultScheduler: ScheduleFunction = systemSetTimeoutZero /** - * Creates a notify manager, which schedules and batches notifications to subscribers. Query uses a - * single instance of it, exported as {@link notifyManager}. + * Creates a notify manager, which schedules and batches notifications to + * subscribers. Query uses a single instance of it, exported as + * {@link notifyManager}. + * * @returns A new notify manager. */ export function createNotifyManager() { @@ -59,10 +61,11 @@ export function createNotifyManager() { return { /** - * Batches all updates scheduled inside the passed callback. - * This is mainly used internally to optimize query client updating. - * Batches can be nested; the queue is only flushed once the outermost `batch` call finishes. - * The return value of `callback` is passed through. + * Batches all updates scheduled inside the passed callback. This is mainly + * used internally to optimize query client updating. Batches can be nested; + * the queue is only flushed once the outermost `batch` call finishes. The + * return value of `callback` is passed through. + * * @param callback - The function to run in the batch. * @returns The return value of `callback`. */ @@ -81,8 +84,10 @@ export function createNotifyManager() { }, /** * All calls to the wrapped function will be batched. + * * @param callback - The function to wrap. - * @returns A function that schedules a call to `callback` with the given arguments. + * @returns A function that schedules a call to `callback` with the given + * arguments. */ batchCalls: >( callback: BatchCallsCallback, @@ -94,51 +99,60 @@ export function createNotifyManager() { } }, /** - * Schedules a function to be run on the next batch. - * By default, the batch is run with a `setTimeout`, but this can be configured via `setScheduler`. + * Schedules a function to be run on the next batch. By default, the batch + * is run with a `setTimeout`, but this can be configured via + * `setScheduler`. */ schedule, /** - * Use this method to set a custom notify function. - * This can be used to for example wrap notifications with `React.act` while running tests. + * Use this method to set a custom notify function. This can be used to for + * example wrap notifications with `React.act` while running tests. + * * @param fn - Receives each notification callback and must call it. */ setNotifyFunction: (fn: NotifyFunction) => { notifyFn = fn }, /** - * Use this method to set a custom function to batch notifications together into a single tick. - * Framework adapters use this to plug in their own batching primitive, so that a single query - * update only triggers one re-render instead of one per subscriber. - * @param fn - Receives a function that runs a batch of notifications and must call it. + * Use this method to set a custom function to batch notifications together + * into a single tick. Framework adapters use this to plug in their own + * batching primitive, so that a single query update only triggers one + * re-render instead of one per subscriber. + * * @example - * ```ts - * import { notifyManager } from '@tanstack/query-core' - * import { batch } from 'solid-js' + * ```ts + * import { notifyManager } from '@tanstack/query-core' + * import { batch } from 'solid-js' + * + * notifyManager.setBatchNotifyFunction(batch) + * ``` * - * notifyManager.setBatchNotifyFunction(batch) - * ``` + * @param fn - Receives a function that runs a batch of notifications and + * must call it. */ setBatchNotifyFunction: (fn: BatchNotifyFunction) => { batchNotifyFn = fn }, /** - * Configures a custom callback that schedules when the next batch runs. - * The default behavior is `setTimeout(callback, 0)`. - * @param fn - Receives a callback that runs the next batch, and schedules it. + * Configures a custom callback that schedules when the next batch runs. The + * default behavior is `setTimeout(callback, 0)`. + * * @example - * ```ts - * import { notifyManager } from '@tanstack/query-core' + * ```ts + * import { notifyManager } from '@tanstack/query-core' + * + * // Schedule batches in the next microtask + * notifyManager.setScheduler(queueMicrotask) * - * // Schedule batches in the next microtask - * notifyManager.setScheduler(queueMicrotask) + * // Schedule batches before the next frame is rendered + * notifyManager.setScheduler(requestAnimationFrame) * - * // Schedule batches before the next frame is rendered - * notifyManager.setScheduler(requestAnimationFrame) + * // Schedule batches some time in the future + * notifyManager.setScheduler((cb) => setTimeout(cb, 10)) + * ``` * - * // Schedule batches some time in the future - * notifyManager.setScheduler((cb) => setTimeout(cb, 10)) - * ``` + * @param fn - Receives a callback that runs the next batch, and schedules + * it. */ setScheduler: (fn: ScheduleFunction) => { scheduleFn = fn @@ -148,7 +162,5 @@ export function createNotifyManager() { // SINGLETON -/** - * Handles scheduling and batching callbacks in TanStack Query. - */ +/** Handles scheduling and batching callbacks in TanStack Query. */ export const notifyManager = createNotifyManager() diff --git a/packages/query-core/src/onlineManager.ts b/packages/query-core/src/onlineManager.ts index f6704ede01a..184801fedb7 100644 --- a/packages/query-core/src/onlineManager.ts +++ b/packages/query-core/src/onlineManager.ts @@ -4,13 +4,13 @@ type Listener = (online: boolean) => void type SetupFn = (setOnline: Listener) => (() => void) | undefined /** - * The `OnlineManager` manages the online state within TanStack Query. It can - * be used to change the default event listeners or to manually change the - * online state. + * The `OnlineManager` manages the online state within TanStack Query. It can be + * used to change the default event listeners or to manually change the online + * state. * * By default, the `onlineManager` assumes an active network connection, and - * listens to the `online` and `offline` events on the `window` object to - * detect changes. + * listens to the `online` and `offline` events on the `window` object to detect + * changes. */ export class OnlineManager extends Subscribable { #online = true @@ -55,23 +55,26 @@ export class OnlineManager extends Subscribable { } /** - * `setEventListener` can be used to set a custom event listener that will - * be used to determine the online state. The provided `setup` function - * receives a `setOnline` callback that should be called with a `boolean` - * whenever the online state changes. - * @param setup - Receives the `setOnline` callback, registers the event listener, and may return - * a cleanup function that is called when the listener is replaced or no longer needed. + * `setEventListener` can be used to set a custom event listener that will be + * used to determine the online state. The provided `setup` function receives + * a `setOnline` callback that should be called with a `boolean` whenever the + * online state changes. + * * @example - * ```ts - * import NetInfo from '@react-native-community/netinfo' - * import { onlineManager } from '@tanstack/query-core' + * ```ts + * import NetInfo from '@react-native-community/netinfo' + * import { onlineManager } from '@tanstack/query-core' * - * onlineManager.setEventListener((setOnline) => { - * return NetInfo.addEventListener((state) => { - * setOnline(!!state.isConnected) + * onlineManager.setEventListener((setOnline) => { + * return NetInfo.addEventListener((state) => { + * setOnline(!!state.isConnected) + * }) * }) - * }) - * ``` + * ``` + * + * @param setup - Receives the `setOnline` callback, registers the event + * listener, and may return a cleanup function that is called when the + * listener is replaced or no longer needed. */ setEventListener(setup: SetupFn): void { this.#setup = setup @@ -81,17 +84,19 @@ export class OnlineManager extends Subscribable { /** * `setOnline` can be used to manually set the online state. - * @param online - The online state. + * * @example - * ```ts - * import { onlineManager } from '@tanstack/query-core' + * ```ts + * import { onlineManager } from '@tanstack/query-core' * - * // Set to online - * onlineManager.setOnline(true) + * // Set to online + * onlineManager.setOnline(true) * - * // Set to offline - * onlineManager.setOnline(false) - * ``` + * // Set to offline + * onlineManager.setOnline(false) + * ``` + * + * @param online - The online state. */ setOnline(online: boolean): void { const changed = this.#online !== online @@ -106,6 +111,7 @@ export class OnlineManager extends Subscribable { /** * `isOnline` can be used to get the current online state. + * * @returns `true` if online. */ isOnline(): boolean { @@ -114,6 +120,7 @@ export class OnlineManager extends Subscribable { } /** - * Singleton instance of {@link OnlineManager}, used to manage and observe the online state within TanStack Query. + * Singleton instance of {@link OnlineManager}, used to manage and observe the + * online state within TanStack Query. */ export const onlineManager = new OnlineManager() diff --git a/packages/query-core/src/queriesObserver.ts b/packages/query-core/src/queriesObserver.ts index ca4c25bb802..69a05b5166a 100644 --- a/packages/query-core/src/queriesObserver.ts +++ b/packages/query-core/src/queriesObserver.ts @@ -11,6 +11,7 @@ import type { QueryClient } from './queryClient' /** * Returns the items of `array1` that are not in `array2`. + * * @param array1 - The items to filter. * @param array2 - The items to exclude. * @returns A new array with the items of `array1` that are not in `array2`. @@ -26,9 +27,7 @@ type CombineFn = ( result: Array, ) => TCombinedResult -/** - * Options for a `QueriesObserver` that apply to all of its queries at once. - */ +/** Options for a `QueriesObserver` that apply to all of its queries at once. */ export interface QueriesObserverOptions< TCombinedResult = Array, > { @@ -44,22 +43,23 @@ export interface QueriesObserverOptions< } /** - * A `QueriesObserver` watches an array of queries at once, exposing them as - * a single array of `QueryObserverResult`s (or, when a `combine` option is - * given, as a combined value derived from that array). It manages one - * internal `QueryObserver` per query, and is the primitive that framework - * adapters (e.g. `useQueries`) build their hooks on top of. + * A `QueriesObserver` watches an array of queries at once, exposing them as a + * single array of `QueryObserverResult`s (or, when a `combine` option is given, + * as a combined value derived from that array). It manages one internal + * `QueryObserver` per query, and is the primitive that framework adapters (e.g. + * `useQueries`) build their hooks on top of. + * * @example - * ```ts - * const observer = new QueriesObserver(queryClient, [ - * { queryKey: ['post', 1], queryFn: fetchPost }, - * { queryKey: ['post', 2], queryFn: fetchPost }, - * ]) + * ```ts + * const observer = new QueriesObserver(queryClient, [ + * { queryKey: ['post', 1], queryFn: fetchPost }, + * { queryKey: ['post', 2], queryFn: fetchPost }, + * ]) * - * const unsubscribe = observer.subscribe((result) => { - * console.log(result) - * }) - * ``` + * const unsubscribe = observer.subscribe((result) => { + * console.log(result) + * }) + * ``` */ export class QueriesObserver< TCombinedResult = Array, @@ -119,19 +119,22 @@ export class QueriesObserver< } /** - * Replaces the set of queries being observed. Existing `QueryObserver`s - * are reused for queries that match an already-observed query hash; - * observers for queries that are no longer present are destroyed, and new - * observers are created and subscribed to for newly added queries. - * @param queries - The options of the queries to observe. - * @param options - Replaces the observer's options, e.g. its `combine` function. + * Replaces the set of queries being observed. Existing `QueryObserver`s are + * reused for queries that match an already-observed query hash; observers for + * queries that are no longer present are destroyed, and new observers are + * created and subscribed to for newly added queries. + * * @example - * ```ts - * observer.setQueries([ - * { queryKey: ['post', 1], queryFn: fetchPost }, - * { queryKey: ['post', 3], queryFn: fetchPost }, - * ]) - * ``` + * ```ts + * observer.setQueries([ + * { queryKey: ['post', 1], queryFn: fetchPost }, + * { queryKey: ['post', 3], queryFn: fetchPost }, + * ]) + * ``` + * + * @param queries - The options of the queries to observe. + * @param options - Replaces the observer's options, e.g. its `combine` + * function. */ setQueries( queries: Array, @@ -206,23 +209,26 @@ export class QueriesObserver< } /** - * Returns the most recently computed array of `QueryObserverResult`s, one - * per observed query, in the same order as the queries passed to the - * constructor or `setQueries`. - * @returns The current results. + * Returns the most recently computed array of `QueryObserverResult`s, one per + * observed query, in the same order as the queries passed to the constructor + * or `setQueries`. + * * @example - * ```ts - * const results = observer.getCurrentResult() - * const data = results.map((result) => result.data) - * ``` + * ```ts + * const results = observer.getCurrentResult() + * const data = results.map((result) => result.data) + * ``` + * + * @returns The current results. */ getCurrentResult(): Array { return this.#result } /** - * Returns the underlying `Query` instances currently being observed, in - * the same order as the queries passed to the constructor or `setQueries`. + * Returns the underlying `Query` instances currently being observed, in the + * same order as the queries passed to the constructor or `setQueries`. + * * @returns The observed queries. */ getQueries() { @@ -230,9 +236,9 @@ export class QueriesObserver< } /** - * Returns the underlying `QueryObserver` instances this observer manages, - * in the same order as the queries passed to the constructor or - * `setQueries`. + * Returns the underlying `QueryObserver` instances this observer manages, in + * the same order as the queries passed to the constructor or `setQueries`. + * * @returns The managed query observers. */ getObservers() { @@ -240,15 +246,21 @@ export class QueriesObserver< } /** - * The `QueriesObserver` counterpart of {@link QueryObserver#getOptimisticResult} — computes - * the result for the given (already-defaulted) queries right now, synchronously. Called by - * framework adapters (e.g. `useQueries`) ahead of subscribing, returning a tuple of the raw - * per-query results, a function to compute the combined result from them, and a function to - * wrap the results for property-access tracking. - * @param queries - The defaulted options of the queries to compute the result for. - * @param combine - The `combine` function used by the returned `combineResult`, if any. - * @returns A tuple of the per-query results, a function that computes the combined result, and a - * function that returns the results wrapped for property-access tracking. + * The `QueriesObserver` counterpart of + * {@link QueryObserver#getOptimisticResult} — computes the result for the + * given (already-defaulted) queries right now, synchronously. Called by + * framework adapters (e.g. `useQueries`) ahead of subscribing, returning a + * tuple of the raw per-query results, a function to compute the combined + * result from them, and a function to wrap the results for property-access + * tracking. + * + * @param queries - The defaulted options of the queries to compute the result + * for. + * @param combine - The `combine` function used by the returned + * `combineResult`, if any. + * @returns A tuple of the per-query results, a function that computes the + * combined result, and a function that returns the results wrapped for + * property-access tracking. */ getOptimisticResult( queries: Array, diff --git a/packages/query-core/src/query.ts b/packages/query-core/src/query.ts index bd895805ab0..e8998a77359 100644 --- a/packages/query-core/src/query.ts +++ b/packages/query-core/src/query.ts @@ -46,43 +46,45 @@ interface QueryConfig< } /** - * The raw state stored on a `Query` instance. This is the underlying state - * that observer results (e.g. `QueryObserverResult`) are derived from. + * The raw state stored on a `Query` instance. This is the underlying state that + * observer results (e.g. `QueryObserverResult`) are derived from. */ export interface QueryState { - /** - * The last successfully resolved data for the query. - */ + /** The last successfully resolved data for the query. */ data: TData | undefined - /** - * The number of times the query has successfully resolved. - */ + /** The number of times the query has successfully resolved. */ dataUpdateCount: number /** - * The timestamp for when the query most recently returned the `status` as `"success"`. + * The timestamp for when the query most recently returned the `status` as + * `"success"`. */ dataUpdatedAt: number /** * The error object for the query, if the last attempt resulted in an error. + * * - Defaults to `null`. */ error: TError | null /** - * The sum of all errors, incremented every time the query resolves with an error. + * The sum of all errors, incremented every time the query resolves with an + * error. */ errorUpdateCount: number /** - * The timestamp for when the query most recently returned the `status` as `"error"`. + * The timestamp for when the query most recently returned the `status` as + * `"error"`. */ errorUpdatedAt: number /** * The failure count for the current fetch. + * * - Incremented every time the fetch fails. * - Reset to `0` when the fetch succeeds. */ fetchFailureCount: number /** * The reason the current fetch failed, as reported by the retryer. + * * - Reset to `null` when the fetch succeeds. */ fetchFailureReason: TError | null @@ -93,11 +95,13 @@ export interface QueryState { fetchMeta: FetchMeta | null /** * Whether the query has been marked as invalidated via `invalidate()`. + * * - Reset to `false` whenever the query resolves successfully. */ isInvalidated: boolean /** * The status of the query. + * * - `pending` if there's no cached data and no attempt was finished yet. * - `error` if the last attempt resulted in an error. * - `success` if the query has data. @@ -105,6 +109,7 @@ export interface QueryState { status: QueryStatus /** * The fetch status of the query. + * * - `fetching`: the `queryFn` is currently executing. * - `paused`: a fetch wanted to run but has been paused (see network mode). * - `idle`: the query is not fetching. @@ -113,8 +118,9 @@ export interface QueryState { } /** - * The context passed to a {@link QueryBehavior}'s `onFetch`, which can replace `fetchFn` to change - * how the query fetches (e.g. to fetch pages for an infinite query). + * The context passed to a {@link QueryBehavior}'s `onFetch`, which can replace + * `fetchFn` to change how the query fetches (e.g. to fetch pages for an + * infinite query). */ export interface FetchContext< TQueryFnData, @@ -123,37 +129,27 @@ export interface FetchContext< TQueryKey extends QueryKey = QueryKey, > { /** - * The function that runs the fetch. By default it calls `queryFn`; `onFetch` can replace it. + * The function that runs the fetch. By default it calls `queryFn`; `onFetch` + * can replace it. */ fetchFn: () => unknown | Promise - /** - * The options of this fetch. - */ + /** The options of this fetch. */ fetchOptions?: FetchOptions - /** - * The `AbortSignal` that aborts when the fetch is cancelled. - */ + /** The `AbortSignal` that aborts when the fetch is cancelled. */ signal: AbortSignal - /** - * The options of the query. - */ + /** The options of the query. */ options: QueryOptions - /** - * The `QueryClient` the query belongs to. - */ + /** The `QueryClient` the query belongs to. */ client: QueryClient - /** - * The key of the query. - */ + /** The key of the query. */ queryKey: TQueryKey - /** - * The state of the query when the fetch starts. - */ + /** The state of the query when the fetch starts. */ state: QueryState } /** - * Customizes how a query fetches, e.g. the behavior that fetches the pages of an infinite query. + * Customizes how a query fetches, e.g. the behavior that fetches the pages of + * an infinite query. */ export interface QueryBehavior< TQueryFnData = unknown, @@ -162,7 +158,8 @@ export interface QueryBehavior< TQueryKey extends QueryKey = QueryKey, > { /** - * Called before each fetch of the query, e.g. to replace `fetchFn` in the context. + * Called before each fetch of the query, e.g. to replace `fetchFn` in the + * context. */ onFetch: ( context: FetchContext, @@ -171,37 +168,35 @@ export interface QueryBehavior< } /** - * The direction an infinite query fetches in: `'forward'` for the next page, `'backward'` for the - * previous one. + * The direction an infinite query fetches in: `'forward'` for the next page, + * `'backward'` for the previous one. */ export type FetchDirection = 'forward' | 'backward' /** - * Metadata for a fetch, e.g. the direction when an infinite query fetches more pages. + * Metadata for a fetch, e.g. the direction when an infinite query fetches more + * pages. */ export interface FetchMeta { /** - * Set when an infinite query fetches another page, with the direction to fetch in. + * Set when an infinite query fetches another page, with the direction to + * fetch in. */ fetchMore?: { direction: FetchDirection } } -/** - * Options for a single fetch of a query. - */ +/** Options for a single fetch of a query. */ export interface FetchOptions { /** - * If `true`, an in-flight fetch is cancelled before starting a new one, when the query already - * has data. Otherwise, the in-flight fetch is reused. + * If `true`, an in-flight fetch is cancelled before starting a new one, when + * the query already has data. Otherwise, the in-flight fetch is reused. */ cancelRefetch?: boolean - /** - * Metadata of the fetch, stored in the query's `fetchMeta` state. - */ + /** Metadata of the fetch, stored in the query's `fetchMeta` state. */ meta?: FetchMeta /** - * A promise to use for the first attempt instead of calling `fetchFn`, e.g. a pending promise - * restored by `hydrate`. + * A promise to use for the first attempt instead of calling `fetchFn`, e.g. a + * pending promise restored by `hydrate`. */ initialPromise?: Promise } @@ -247,8 +242,8 @@ interface SetStateAction { } /** - * The actions a query dispatches to update its state, e.g. when it starts fetching, fails, or - * succeeds. + * The actions a query dispatches to update its state, e.g. when it starts + * fetching, fails, or succeeds. */ export type Action = | ContinueAction @@ -267,18 +262,19 @@ export type Action = * state (data/error/status), and the observers currently subscribed to it. * * Instances are created and managed internally by `QueryCache`; application - * code typically interacts with queries indirectly through `QueryClient` or - * a framework hook like `useQuery`. Direct access to a `Query` instance is + * code typically interacts with queries indirectly through `QueryClient` or a + * framework hook like `useQuery`. Direct access to a `Query` instance is * possible via `queryCache.find()`/`findAll()` for inspecting cache state. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() - * const query = queryCache.find({ queryKey: ['posts'] }) + * ```ts + * const queryCache = queryClient.getQueryCache() + * const query = queryCache.find({ queryKey: ['posts'] }) * - * if (query) { - * console.log(query.state.dataUpdatedAt) - * } - * ``` + * if (query) { + * console.log(query.state.dataUpdatedAt) + * } + * ``` */ export class Query< TQueryFnData = unknown, @@ -318,6 +314,7 @@ export class Query< } /** * The `meta` object passed in the query's options, if any. + * * @returns The query's `meta`, or `undefined` if none was set. */ get meta(): QueryMeta | undefined { @@ -326,8 +323,10 @@ export class Query< /** * `'infinite'` for an infinite query, otherwise `undefined`. + * + * @returns The type of the query, set from the `_type` option (e.g. + * `'infinite'`). * @internal - * @returns The type of the query, set from the `_type` option (e.g. `'infinite'`). */ get queryType() { return this.#queryType @@ -336,6 +335,7 @@ export class Query< /** * The promise for the currently in-flight fetch, if the query is fetching. * `undefined` when the query is not fetching. + * * @returns The promise of the in-flight fetch, or `undefined`. */ get promise(): Promise | undefined { @@ -343,10 +343,12 @@ export class Query< } /** - * Replaces the query's options and applies their `gcTime`. If the query has no data yet, it gets - * the `initialData` from the new options, if any. + * Replaces the query's options and applies their `gcTime`. If the query has + * no data yet, it gets the `initialData` from the new options, if any. + * + * @param options - The new query options, merged on top of the query's + * default options. * @internal - * @param options - The new query options, merged on top of the query's default options. */ setOptions( options?: QueryOptions, @@ -379,11 +381,13 @@ export class Query< /** * Writes new data to the query and marks it as successfully fetched. - * @internal - * @param newData - The data to write. Structural sharing with the current data is applied. - * @param options - Set `updatedAt` to override the timestamp, and `manual` to mark the write as - * manual (e.g. from `queryClient.setQueryData`). + * + * @param newData - The data to write. Structural sharing with the current + * data is applied. + * @param options - Set `updatedAt` to override the timestamp, and `manual` to + * mark the write as manual (e.g. from `queryClient.setQueryData`). * @returns The data that was written. + * @internal */ setData( newData: TData, @@ -403,9 +407,11 @@ export class Query< } /** - * Merges the given partial state directly into this query's state, notifying observers. Used - * by persistence and broadcast plugins to restore a state snapshot, and by devtools to let a - * user manually trigger a loading/error state or edit the cached data. + * Merges the given partial state directly into this query's state, notifying + * observers. Used by persistence and broadcast plugins to restore a state + * snapshot, and by devtools to let a user manually trigger a loading/error + * state or edit the cached data. + * * @param state - The partial state to merge into the query's state. */ setState(state: Partial>): void { @@ -414,15 +420,19 @@ export class Query< /** * Cancels the query's currently in-flight fetch, if any. + * * - Returns a promise that resolves once the cancellation has settled. * - If no fetch is in progress, resolves immediately. - * @param options - Set `revert` to restore the state from before the fetch started, and `silent` - * to suppress the cancellation error when a new fetch replaces the cancelled one. - * @returns A promise that resolves once the cancellation has settled. + * * @example - * ```ts - * await query.cancel() - * ``` + * ```ts + * await query.cancel() + * ``` + * + * @param options - Set `revert` to restore the state from before the fetch + * started, and `silent` to suppress the cancellation error when a new fetch + * replaces the cancelled one. + * @returns A promise that resolves once the cancellation has settled. */ cancel(options?: CancelOptions): Promise { const promise = this.#retryer?.promise @@ -432,8 +442,9 @@ export class Query< /** * Clears the query's garbage collection timeout and silently cancels any - * in-flight fetch. Called by `QueryCache` when the query is removed from - * the cache. + * in-flight fetch. Called by `QueryCache` when the query is removed from the + * cache. + * * @see {@link Query#cancel} */ override destroy(): void { @@ -444,8 +455,10 @@ export class Query< /** * The state the query was created with. + * + * @returns The state the query had when it was first created, used by + * {@link Query#reset}. * @internal - * @returns The state the query had when it was first created, used by {@link Query#reset}. */ get resetState(): QueryState { return this.#initialState @@ -464,6 +477,7 @@ export class Query< /** * Returns `true` if the query has at least one observer for which `enabled` * does not resolve to `false`. + * * @returns `true` if the query has an enabled observer. */ isActive(): boolean { @@ -475,10 +489,12 @@ export class Query< /** * Returns `true` if the query is disabled, meaning it will not fetch * automatically. + * * - If the query has observers, it is disabled when none of them are active * (see `isActive`). * - If the query has no observers, it is disabled when its `queryFn` is * `skipToken` or it has never been fetched. + * * @returns `true` if the query is disabled. */ isDisabled(): boolean { @@ -492,6 +508,7 @@ export class Query< /** * Returns `true` if the query has been fetched, i.e. it has resolved with * either data or an error at least once. + * * @returns `true` if the query has been fetched. */ isFetched() { @@ -501,6 +518,7 @@ export class Query< /** * Returns `true` if the query has at least one observer configured with * `staleTime: 'static'`, meaning it is treated as never stale. + * * @returns `true` if the query is static. */ isStatic(): boolean { @@ -516,19 +534,22 @@ export class Query< /** * Returns `true` if the query is stale. - * - If the query has observers, defers to whether any observer's current - * result reports `isStale` (which accounts for each observer's own - * `staleTime` and `enabled` state). - * - If the query has no observers, it is considered stale when it has no - * data or has been invalidated. + * + * - If the query has observers, defers to whether any observer's current result + * reports `isStale` (which accounts for each observer's own `staleTime` and + * `enabled` state). + * - If the query has no observers, it is considered stale when it has no data + * or has been invalidated. + * + * @example + * ```ts + * if (query.isStale()) { + * // refetch or otherwise treat the cached data as outdated + * } + * ``` + * * @returns `true` if the query is stale. * @see {@link Query#isStaleByTime} - * @example - * ```ts - * if (query.isStale()) { - * // refetch or otherwise treat the cached data as outdated - * } - * ``` */ isStale(): boolean { // check observers first, their `isStale` has the source of truth @@ -545,18 +566,22 @@ export class Query< /** * Returns `true` if the query's data is stale relative to the given * `staleTime` (defaults to `0`). + * * - A query with no data is always stale. * - `staleTime: 'static'` is never stale. * - An invalidated query is always stale. * - Otherwise, staleness is based on elapsed time since `dataUpdatedAt`. - * @param staleTime - The time, in milliseconds, after which data is considered stale, or - * `'static'` to never treat existing data as stale. A query without data is stale either way. + * + * @example + * ```ts + * const isStale = query.isStaleByTime(1000 * 60) + * ``` + * + * @param staleTime - The time, in milliseconds, after which data is + * considered stale, or `'static'` to never treat existing data as stale. A + * query without data is stale either way. * @returns `true` if the query's data is stale. * @see {@link Query#isStale} - * @example - * ```ts - * const isStale = query.isStaleByTime(1000 * 60) - * ``` */ isStaleByTime(staleTime: StaleTime = 0): boolean { // no data is always stale @@ -576,8 +601,9 @@ export class Query< } /** - * Refetches the query when the window regains focus, if an observer wants that, and continues a - * paused fetch. + * Refetches the query when the window regains focus, if an observer wants + * that, and continues a paused fetch. + * * @internal */ onFocus(): void { @@ -590,8 +616,9 @@ export class Query< } /** - * Refetches the query when the app reconnects, if an observer wants that, and continues a paused - * fetch. + * Refetches the query when the app reconnects, if an observer wants that, and + * continues a paused fetch. + * * @internal */ onOnline(): void { @@ -605,9 +632,10 @@ export class Query< /** * Subscribes an observer to the query and stops its garbage collection. + * + * @param observer - The observer to add. Adding an observer that is already + * subscribed does nothing. * @internal - * @param observer - The observer to add. Adding an observer that is already subscribed does - * nothing. */ addObserver(observer: QueryObserver): void { if (!this.observers.includes(observer)) { @@ -622,10 +650,12 @@ export class Query< /** * Unsubscribes an observer from the query. + * + * @param observer - The observer to remove. When the last observer is + * removed, the in-flight fetch is cancelled if its abort signal was + * consumed (otherwise only its retries are stopped), and garbage collection + * is scheduled. * @internal - * @param observer - The observer to remove. When the last observer is removed, the in-flight - * fetch is cancelled if its abort signal was consumed (otherwise only its retries are stopped), - * and garbage collection is scheduled. */ removeObserver(observer: QueryObserver): void { const index = this.observers.indexOf(observer) @@ -656,13 +686,15 @@ export class Query< /** * Returns the number of observers currently subscribed to this query. - * @returns The number of observers. + * * @example - * ```ts - * if (query.getObserversCount() === 0) { - * // no component is currently watching this query - * } - * ``` + * ```ts + * if (query.getObserversCount() === 0) { + * // no component is currently watching this query + * } + * ``` + * + * @returns The number of observers. */ getObserversCount(): number { return this.observers.length @@ -672,10 +704,11 @@ export class Query< * Marks the query as invalidated, unless it is already invalidated. This * updates `state.isInvalidated` and notifies observers, but does not by * itself trigger a refetch. + * * @example - * ```ts - * query.invalidate() - * ``` + * ```ts + * query.invalidate() + * ``` */ invalidate(): void { if (!this.state.isInvalidated) { @@ -686,19 +719,21 @@ export class Query< /** * Fetches the query, i.e. runs its `queryFn` (through any configured * retryer/behavior) and updates the query's state with the result. - * - If a fetch is already in flight, returns its promise instead of - * starting a new one, unless `fetchOptions.cancelRefetch` is set and the - * query already has data, in which case the current fetch is silently - * cancelled first. - * - If `options` is passed, it replaces the query's current options - * before fetching. - * @param options - Query options that replace the query's current options before fetching. They - * are not applied when an in-flight fetch is reused. - * @param fetchOptions - Set `cancelRefetch` to cancel an in-flight fetch first (only if the query - * already has data), and `meta` to pass extra information to the query's behavior. - * @returns A promise that resolves with the fetched data, or rejects with the fetch error. If the - * fetch is cancelled with `revert` while the query has data, it resolves with the restored data - * instead. + * + * - If a fetch is already in flight, returns its promise instead of starting a + * new one, unless `fetchOptions.cancelRefetch` is set and the query already + * has data, in which case the current fetch is silently cancelled first. + * - If `options` is passed, it replaces the query's current options before + * fetching. + * + * @param options - Query options that replace the query's current options + * before fetching. They are not applied when an in-flight fetch is reused. + * @param fetchOptions - Set `cancelRefetch` to cancel an in-flight fetch + * first (only if the query already has data), and `meta` to pass extra + * information to the query's behavior. + * @returns A promise that resolves with the fetched data, or rejects with the + * fetch error. If the fetch is cancelled with `revert` while the query has + * data, it resolves with the restored data instead. */ async fetch( options?: QueryOptions, @@ -1018,10 +1053,11 @@ export class Query< /** * Returns the state changes applied when a query starts fetching. - * @param data - The query's current data. If it is `undefined`, the query is also reset to - * `'pending'` with no error. - * @param options - The query options, whose `networkMode` decides whether the query is `'fetching'` - * or `'paused'`. + * + * @param data - The query's current data. If it is `undefined`, the query is + * also reset to `'pending'` with no error. + * @param options - The query options, whose `networkMode` decides whether the + * query is `'fetching'` or `'paused'`. * @returns The partial query state for a starting fetch. */ export function fetchState< @@ -1047,8 +1083,10 @@ export function fetchState< /** * Returns the state changes applied when a query receives data. + * * @param data - The new data. - * @param dataUpdatedAt - The timestamp the data is recorded with. Defaults to the current time. + * @param dataUpdatedAt - The timestamp the data is recorded with. Defaults to + * the current time. * @returns The partial query state for a successful update. */ function successState(data: TData | undefined, dataUpdatedAt?: number) { @@ -1062,10 +1100,12 @@ function successState(data: TData | undefined, dataUpdatedAt?: number) { } /** - * Returns the initial state of a query, based on its `initialData` and `initialDataUpdatedAt` - * options. + * Returns the initial state of a query, based on its `initialData` and + * `initialDataUpdatedAt` options. + * * @param options - The query options. - * @returns The initial query state: `'success'` if `initialData` is set, otherwise `'pending'`. + * @returns The initial query state: `'success'` if `initialData` is set, + * otherwise `'pending'`. */ function getDefaultState< TQueryFnData, diff --git a/packages/query-core/src/queryCache.ts b/packages/query-core/src/queryCache.ts index cbbff6c2af7..ae83ade7c9c 100644 --- a/packages/query-core/src/queryCache.ts +++ b/packages/query-core/src/queryCache.ts @@ -17,10 +17,11 @@ import type { QueryObserver } from './queryObserver' // TYPES /** - * Global callbacks that fire for every query handled by a `QueryCache`, regardless of which - * component or observer triggered it. Unlike `QueryClient`'s `defaultOptions`, which a query can - * override, these callbacks are always called. Unlike `MutationCacheConfig`'s callbacks, these - * are fire-and-forget: their return value is not awaited before the query settles. + * Global callbacks that fire for every query handled by a `QueryCache`, + * regardless of which component or observer triggered it. Unlike + * `QueryClient`'s `defaultOptions`, which a query can override, these callbacks + * are always called. Unlike `MutationCacheConfig`'s callbacks, these are + * fire-and-forget: their return value is not awaited before the query settles. */ export interface QueryCacheConfig { /** Called when any query in the cache encounters an error. */ @@ -30,7 +31,10 @@ export interface QueryCacheConfig { ) => void /** Called when any query in the cache is successful. */ onSuccess?: (data: unknown, query: Query) => void - /** Called when any query in the cache is settled, either successfully or with an error. */ + /** + * Called when any query in the cache is settled, either successfully or with + * an error. + */ onSettled?: ( data: unknown | undefined, error: DefaultError | null, @@ -78,9 +82,10 @@ interface NotifyEventQueryObserverOptionsUpdated extends NotifyEvent { } /** - * The event passed to a `QueryCache` subscriber. Fired whenever a query is added or removed from - * the cache, its state is updated (e.g. via `query.setState` or `queryClient.removeQueries`), or - * one of its observers is added, removed, or has its results or options updated. + * The event passed to a `QueryCache` subscriber. Fired whenever a query is + * added or removed from the cache, its state is updated (e.g. via + * `query.setState` or `queryClient.removeQueries`), or one of its observers is + * added, removed, or has its results or options updated. */ export type QueryCacheNotifyEvent = | NotifyEventQueryAdded @@ -93,49 +98,39 @@ export type QueryCacheNotifyEvent = type QueryCacheListener = (event: QueryCacheNotifyEvent) => void -/** - * The store a `QueryCache` keeps its queries in, keyed by query hash. - */ +/** The store a `QueryCache` keeps its queries in, keyed by query hash. */ export interface QueryStore { - /** - * Returns whether a query with the given hash is stored. - */ + /** Returns whether a query with the given hash is stored. */ has: (queryHash: string) => boolean - /** - * Stores a query under its hash. - */ + /** Stores a query under its hash. */ set: (queryHash: string, query: Query) => void - /** - * Returns the query with the given hash, if any. - */ + /** Returns the query with the given hash, if any. */ get: (queryHash: string) => Query | undefined - /** - * Removes the query with the given hash. - */ + /** Removes the query with the given hash. */ delete: (queryHash: string) => void - /** - * Returns an iterator over all stored queries. - */ + /** Returns an iterator over all stored queries. */ values: () => IterableIterator } // CLASS /** - * The `QueryCache` is the storage mechanism for TanStack Query. It stores all the data, meta - * information, and state of the queries it contains. + * The `QueryCache` is the storage mechanism for TanStack Query. It stores all + * the data, meta information, and state of the queries it contains. + * + * Normally, you will not interact with the `QueryCache` directly and instead + * use a `QueryClient` for a specific cache. You can subscribe to it (inherited + * from `Subscribable`) to be informed of safe/known updates to the cache, such + * as queries being added, removed, or updated — updates made outside of the + * cache's own tracked mechanisms (e.g. mutating a query's state object + * directly) do not notify subscribers. * - * Normally, you will not interact with the `QueryCache` directly and instead use a `QueryClient` - * for a specific cache. You can subscribe to it (inherited from `Subscribable`) to be informed of - * safe/known updates to the cache, such as queries being added, removed, or updated — updates made - * outside of the cache's own tracked mechanisms (e.g. mutating a query's state object directly) do - * not notify subscribers. * @example - * ```ts - * const unsubscribe = queryCache.subscribe((event) => { - * console.log(event.type, event.query) - * }) - * ``` + * ```ts + * const unsubscribe = queryCache.subscribe((event) => { + * console.log(event.type, event.query) + * }) + * ``` */ export class QueryCache extends Subscribable { #queries: QueryStore @@ -146,25 +141,30 @@ export class QueryCache extends Subscribable { } /** - * Returns the existing `Query` instance for the given options' `queryKey`/`queryHash`, or - * builds and adds a new one to the cache if none exists yet. Used by framework adapters and - * plugins (e.g. broadcast/persistence) that need to get-or-create a `Query` directly, bypassing - * the reactive `QueryObserver` machinery. - * @param client - The client the query belongs to, used to default its options. - * @param options - The query options, including the `queryKey`. A new query is created with the - * options defaulted by {@link QueryClient#defaultQueryOptions}. - * @param state - The initial state of a newly created query, e.g. when hydrating. Ignored if the - * query already exists. - * @returns The existing or newly created query. + * Returns the existing `Query` instance for the given options' + * `queryKey`/`queryHash`, or builds and adds a new one to the cache if none + * exists yet. Used by framework adapters and plugins (e.g. + * broadcast/persistence) that need to get-or-create a `Query` directly, + * bypassing the reactive `QueryObserver` machinery. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() + * ```ts + * const queryCache = queryClient.getQueryCache() * - * const query = queryCache.build(queryClient, { - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) - * ``` + * const query = queryCache.build(queryClient, { + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) + * ``` + * + * @param client - The client the query belongs to, used to default its + * options. + * @param options - The query options, including the `queryKey`. A new query + * is created with the options defaulted by + * {@link QueryClient#defaultQueryOptions}. + * @param state - The initial state of a newly created query, e.g. when + * hydrating. Ignored if the query already exists. + * @returns The existing or newly created query. */ build< TQueryFnData = unknown, @@ -201,9 +201,10 @@ export class QueryCache extends Subscribable { /** * Adds a query to the cache. + * + * @param query - The query to add. If a query with the same hash is already + * cached, nothing happens. * @internal - * @param query - The query to add. If a query with the same hash is already cached, nothing - * happens. */ add(query: Query): void { if (!this.#queries.has(query.queryHash)) { @@ -217,20 +218,23 @@ export class QueryCache extends Subscribable { } /** - * Destroys the given `Query` and removes it from the cache, notifying subscribers with a - * `'removed'` event. A no-op if the query is no longer the one currently stored under its hash - * (e.g. it was already replaced). Used by plugins (e.g. the broadcast client) that mirror - * removals across `QueryCache` instances. - * @param query - The query to remove. + * Destroys the given `Query` and removes it from the cache, notifying + * subscribers with a `'removed'` event. A no-op if the query is no longer the + * one currently stored under its hash (e.g. it was already replaced). Used by + * plugins (e.g. the broadcast client) that mirror removals across + * `QueryCache` instances. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() - * const query = queryCache.find({ queryKey: ['posts'] }) + * ```ts + * const queryCache = queryClient.getQueryCache() + * const query = queryCache.find({ queryKey: ['posts'] }) + * + * if (query) { + * queryCache.remove(query) + * } + * ``` * - * if (query) { - * queryCache.remove(query) - * } - * ``` + * @param query - The query to remove. */ remove(query: Query): void { const queryInMap = this.#queries.get(query.queryHash) @@ -244,12 +248,13 @@ export class QueryCache extends Subscribable { /** * Removes all queries from the cache. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() + * ```ts + * const queryCache = queryClient.getQueryCache() * - * queryCache.clear() - * ``` + * queryCache.clear() + * ``` */ clear(): void { notifyManager.batch(() => { @@ -260,19 +265,21 @@ export class QueryCache extends Subscribable { } /** - * Returns the `Query` instance stored under the given `queryHash`, or `undefined` if none - * exists. Unlike {@link QueryCache#find}, this looks up by the already-computed hash rather - * than by `QueryFilters`. Used by plugins (e.g. broadcast/hydration) that already have a hash - * to look up directly. - * @param queryHash - The hash of the query to look up. - * @returns The query stored under the hash, or `undefined`. + * Returns the `Query` instance stored under the given `queryHash`, or + * `undefined` if none exists. Unlike {@link QueryCache#find}, this looks up by + * the already-computed hash rather than by `QueryFilters`. Used by plugins + * (e.g. broadcast/hydration) that already have a hash to look up directly. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() - * const queryHash = hashKey(['posts']) + * ```ts + * const queryCache = queryClient.getQueryCache() + * const queryHash = hashKey(['posts']) * - * const query = queryCache.get(queryHash) - * ``` + * const query = queryCache.get(queryHash) + * ``` + * + * @param queryHash - The hash of the query to look up. + * @returns The query stored under the hash, or `undefined`. */ get< TQueryFnData = unknown, @@ -289,37 +296,42 @@ export class QueryCache extends Subscribable { /** * Returns all queries within the cache. - * @returns Every query in the cache. + * * @example - * ```ts - * const queryCache = queryClient.getQueryCache() + * ```ts + * const queryCache = queryClient.getQueryCache() * - * const queries = queryCache.getAll() - * ``` + * const queries = queryCache.getAll() + * ``` + * + * @returns Every query in the cache. */ getAll(): Array { return [...this.#queries.values()] } /** - * A slightly more advanced method that can be used to get an existing query instance from the - * cache. This instance not only contains all the state for the query, but all of the instances, - * and underlying guts of the query as well. If the query does not exist, `undefined` is - * returned. + * A slightly more advanced method that can be used to get an existing query + * instance from the cache. This instance not only contains all the state for + * the query, but all of the instances, and underlying guts of the query as + * well. If the query does not exist, `undefined` is returned. + * + * This is not typically needed for most applications, but can come in handy + * when needing more information about a query in rare scenarios (e.g. looking + * at `query.state.dataUpdatedAt` to decide whether a query is fresh enough to + * be used as an initial value). * - * This is not typically needed for most applications, but can come in handy when needing more - * information about a query in rare scenarios (e.g. looking at `query.state.dataUpdatedAt` to - * decide whether a query is fresh enough to be used as an initial value). - * @param filters - The filters to match, including the required `queryKey`. `exact` defaults to - * `true`. - * @returns The first matching query, or `undefined`. - * @see {@link QueryCache#findAll} * @example - * ```ts - * const queryCache = queryClient.getQueryCache() + * ```ts + * const queryCache = queryClient.getQueryCache() + * + * const query = queryCache.find({ queryKey: ['posts'] }) + * ``` * - * const query = queryCache.find({ queryKey: ['posts'] }) - * ``` + * @param filters - The filters to match, including the required `queryKey`. + * `exact` defaults to `true`. + * @returns The first matching query, or `undefined`. + * @see {@link QueryCache#findAll} */ find( filters: WithRequired, @@ -332,20 +344,24 @@ export class QueryCache extends Subscribable { } /** - * An even more advanced method that can be used to get existing query instances from the cache - * that partially match a query key. If no queries match, an empty array is returned. + * An even more advanced method that can be used to get existing query + * instances from the cache that partially match a query key. If no queries + * match, an empty array is returned. + * + * This is not typically needed for most applications, but can come in handy + * when needing more information about queries in rare scenarios. * - * This is not typically needed for most applications, but can come in handy when needing more - * information about queries in rare scenarios. - * @param filters - The filters to match. Without filters, every query is returned. - * @returns The matching queries. - * @see {@link QueryCache#find} * @example - * ```ts - * const queryCache = queryClient.getQueryCache() + * ```ts + * const queryCache = queryClient.getQueryCache() + * + * const queries = queryCache.findAll({ queryKey: ['posts'] }) + * ``` * - * const queries = queryCache.findAll({ queryKey: ['posts'] }) - * ``` + * @param filters - The filters to match. Without filters, every query is + * returned. + * @returns The matching queries. + * @see {@link QueryCache#find} */ findAll(filters: QueryFilters = {}): Array { const queries = this.getAll() @@ -356,8 +372,9 @@ export class QueryCache extends Subscribable { /** * Notifies every cache listener of an event, in one batch. - * @internal + * * @param event - The event passed to every listener. + * @internal */ notify(event: QueryCacheNotifyEvent): void { notifyManager.batch(() => { @@ -369,6 +386,7 @@ export class QueryCache extends Subscribable { /** * Calls {@link Query#onFocus} on every cached query, in one batch. + * * @internal */ onFocus(): void { @@ -381,6 +399,7 @@ export class QueryCache extends Subscribable { /** * Calls {@link Query#onOnline} on every cached query, in one batch. + * * @internal */ onOnline(): void { diff --git a/packages/query-core/src/queryClient.ts b/packages/query-core/src/queryClient.ts index 3d8e3e6f690..21f7f258fb6 100644 --- a/packages/query-core/src/queryClient.ts +++ b/packages/query-core/src/queryClient.ts @@ -59,21 +59,23 @@ interface MutationDefaults { // CLASS /** - * `QueryClient` is used to interact with a cache of queries and mutations. It owns a - * `QueryCache` and a `MutationCache` (creating default ones if none are passed in) and holds - * the default options that are applied to queries and mutations created through it. + * `QueryClient` is used to interact with a cache of queries and mutations. It + * owns a `QueryCache` and a `MutationCache` (creating default ones if none are + * passed in) and holds the default options that are applied to queries and + * mutations created through it. + * * @example - * ```ts - * const queryClient = new QueryClient({ - * defaultOptions: { - * queries: { - * staleTime: Infinity, + * ```ts + * const queryClient = new QueryClient({ + * defaultOptions: { + * queries: { + * staleTime: Infinity, + * }, * }, - * }, - * }) + * }) * - * await queryClient.query({ queryKey: ['posts'], queryFn: fetchPosts }) - * ``` + * await queryClient.query({ queryKey: ['posts'], queryFn: fetchPosts }) + * ``` */ export class QueryClient { #queryCache: QueryCache @@ -95,10 +97,11 @@ export class QueryClient { } /** - * Called by a framework adapter's `QueryClientProvider`-equivalent when it mounts, to start - * listening for focus/online events and resume paused mutations. Ref-counted via an internal - * mount count, so nested or multiple providers sharing the same `QueryClient` don't tear down - * the shared listeners until the last one unmounts. + * Called by a framework adapter's `QueryClientProvider`-equivalent when it + * mounts, to start listening for focus/online events and resume paused + * mutations. Ref-counted via an internal mount count, so nested or multiple + * providers sharing the same `QueryClient` don't tear down the shared + * listeners until the last one unmounts. */ mount(): void { this.#mountCount++ @@ -120,8 +123,8 @@ export class QueryClient { /** * The inverse of {@link QueryClient#mount} — called by a framework adapter's - * `QueryClientProvider`-equivalent when it unmounts. Only tears down the focus/online - * listeners once the mount count returns to `0`. + * `QueryClientProvider`-equivalent when it unmounts. Only tears down the + * focus/online listeners once the mount count returns to `0`. */ unmount(): void { this.#mountCount-- @@ -135,18 +138,21 @@ export class QueryClient { } /** - * Returns the number of queries in the cache that are currently fetching, optionally - * matching a set of filters. This includes background-fetching, loading new pages, and - * loading more infinite query results. - * @param filters - Narrows down which fetching queries are counted. Without filters, every - * fetching query is counted. - * @returns The number of matching queries whose `fetchStatus` is `'fetching'`. + * Returns the number of queries in the cache that are currently fetching, + * optionally matching a set of filters. This includes background-fetching, + * loading new pages, and loading more infinite query results. + * * @example - * ```ts - * if (queryClient.isFetching()) { - * console.log('At least one query is fetching!') - * } - * ``` + * ```ts + * if (queryClient.isFetching()) { + * console.log('At least one query is fetching!') + * } + * ``` + * + * @param filters - Narrows down which fetching queries are counted. Without + * filters, every fetching query is counted. + * @returns The number of matching queries whose `fetchStatus` is + * `'fetching'`. */ isFetching = QueryFilters>( filters?: TQueryFilters, @@ -156,17 +162,19 @@ export class QueryClient { } /** - * Returns the number of mutations in the cache that are currently pending, optionally - * matching a set of filters. - * @param filters - Narrows down which pending mutations are counted. Without filters, every - * pending mutation is counted. - * @returns The number of matching mutations whose `status` is `'pending'`. + * Returns the number of mutations in the cache that are currently pending, + * optionally matching a set of filters. + * * @example - * ```ts - * if (queryClient.isMutating()) { - * console.log('At least one mutation is pending!') - * } - * ``` + * ```ts + * if (queryClient.isMutating()) { + * console.log('At least one mutation is pending!') + * } + * ``` + * + * @param filters - Narrows down which pending mutations are counted. Without + * filters, every pending mutation is counted. + * @returns The number of matching mutations whose `status` is `'pending'`. */ isMutating< TMutationFilters extends MutationFilters = MutationFilters, @@ -175,13 +183,17 @@ export class QueryClient { } /** - * Imperative (non-reactive) way to retrieve data for a QueryKey. - * Should only be used in callbacks or functions where reading the latest data is necessary, e.g. for optimistic updates. + * Imperative (non-reactive) way to retrieve data for a QueryKey. Should only + * be used in callbacks or functions where reading the latest data is + * necessary, e.g. for optimistic updates. + * + * Hint: Do not use this function inside a component, because it won't receive + * updates. Use `useQuery` to create a `QueryObserver` that subscribes to + * changes. * - * Hint: Do not use this function inside a component, because it won't receive updates. - * Use `useQuery` to create a `QueryObserver` that subscribes to changes. * @param queryKey - The query key of the query to read. - * @returns The cached data for the query, or `undefined` if no query with this key has been observed yet. + * @returns The cached data for the query, or `undefined` if no query with + * this key has been observed yet. * @see {@link QueryClient#getQueriesData} */ getQueryData< @@ -196,13 +208,16 @@ export class QueryClient { } /** - * Returns the cached data of a query, or fetches it if there is none. With `revalidateIfStale`, - * stale cached data is also refetched in the background. - * @param options - The query options. If the query has no cached data yet, it is fetched with - * these options. - * @returns A promise that resolves to the cached data, or to the fetched data if nothing was - * cached yet. - * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) instead. This method will be removed in the next major version. + * Returns the cached data of a query, or fetches it if there is none. With + * `revalidateIfStale`, stale cached data is also refetched in the + * background. + * + * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) + * instead. This method will be removed in the next major version. + * @param options - The query options. If the query has no cached data yet, it + * is fetched with these options. + * @returns A promise that resolves to the cached data, or to the fetched data + * if nothing was cached yet. */ ensureQueryData< TQueryFnData, @@ -233,22 +248,26 @@ export class QueryClient { } /** - * Imperative (non-reactive) way to retrieve the cached data of multiple queries at once. - * Only queries matching the given filters are returned; if none match, an empty array is - * returned. - * - * Because the matched queries can hold data of different shapes (e.g. a broad filter can match - * queries with unrelated data types), the `TQueryFnData` generic defaults to `unknown` rather - * than being inferred. Passing a more specific type is a convenience for call sites that know - * every matched query holds the same shape — it is not checked against the actual cache + * Imperative (non-reactive) way to retrieve the cached data of multiple + * queries at once. Only queries matching the given filters are returned; if + * none match, an empty array is returned. + * + * Because the matched queries can hold data of different shapes (e.g. a broad + * filter can match queries with unrelated data types), the `TQueryFnData` + * generic defaults to `unknown` rather than being inferred. Passing a more + * specific type is a convenience for call sites that know every matched query + * holds the same shape — it is not checked against the actual cache * contents. + * + * @example + * ```ts + * const data = queryClient.getQueriesData({ queryKey: ['posts'] }) + * ``` + * * @param filters - The filters that select which queries to read. - * @returns An array of query key and data pairs. The data is `undefined` for a query with no cached data. + * @returns An array of query key and data pairs. The data is `undefined` for + * a query with no cached data. * @see {@link QueryClient#getQueryData} - * @example - * ```ts - * const data = queryClient.getQueriesData({ queryKey: ['posts'] }) - * ``` */ getQueriesData< TQueryFnData = unknown, @@ -261,26 +280,31 @@ export class QueryClient { } /** - * Synchronous way to immediately update a query's cached data. If the updater (or the value - * passed) resolves to `undefined`, the cache is left untouched and no query is created; - * otherwise, if the query does not exist yet, it will be created. To update multiple queries - * at once by partially matching query keys, use {@link QueryClient#setQueriesData} instead. + * Synchronous way to immediately update a query's cached data. If the updater + * (or the value passed) resolves to `undefined`, the cache is left untouched + * and no query is created; otherwise, if the query does not exist yet, it + * will be created. To update multiple queries at once by partially matching + * query keys, use {@link QueryClient#setQueriesData} instead. + * + * Updates must be performed immutably: do not mutate `oldData`, or data + * previously retrieved via {@link QueryClient#getQueryData}, in place. * - * Updates must be performed immutably: do not mutate `oldData`, or data previously retrieved - * via {@link QueryClient#getQueryData}, in place. - * @param queryKey - The query key to set data for. - * @param updater - Either the new data, or a function that receives the current data (which - * may be `undefined`) and returns the new data. - * @param options - Set `updatedAt` to override the timestamp the written data is recorded with. - * @returns The data that was written, or `undefined` if the updater returned `undefined` — in that case - * the write is skipped and the cache is left unchanged. * @example - * ```ts - * queryClient.setQueryData(['posts'], newPosts) + * ```ts + * queryClient.setQueryData(['posts'], newPosts) + * + * // Or, using an updater function that receives the current data: + * queryClient.setQueryData(['posts'], (oldPosts) => [...oldPosts, newPost]) + * ``` * - * // Or, using an updater function that receives the current data: - * queryClient.setQueryData(['posts'], (oldPosts) => [...oldPosts, newPost]) - * ``` + * @param queryKey - The query key to set data for. + * @param updater - Either the new data, or a function that receives the + * current data (which may be `undefined`) and returns the new data. + * @param options - Set `updatedAt` to override the timestamp the written data + * is recorded with. + * @returns The data that was written, or `undefined` if the updater returned + * `undefined` — in that case the write is skipped and the cache is left + * unchanged. */ setQueryData< TQueryFnData = unknown, @@ -318,22 +342,27 @@ export class QueryClient { } /** - * Synchronous way to immediately update the cached data of multiple queries at once, using - * filters or partial query key matching. Only queries that already exist and match the given - * filters are updated; no new cache entries are created. Internally this calls - * {@link QueryClient#setQueryData} for each matching query. - * @param filters - The filters that select which existing queries to update. - * @param updater - Either the new data, or a function that receives each matched query's current - * data (which may be `undefined`) and returns the new data. - * @param options - Set `updatedAt` to override the timestamp the written data is recorded with. - * @returns One `[queryKey, data]` tuple per matched query, in the same shape and with the same - * `undefined` case as {@link QueryClient#setQueryData}. + * Synchronous way to immediately update the cached data of multiple queries + * at once, using filters or partial query key matching. Only queries that + * already exist and match the given filters are updated; no new cache entries + * are created. Internally this calls {@link QueryClient#setQueryData} for each + * matching query. + * * @example - * ```ts - * queryClient.setQueriesData({ queryKey: ['posts'] }, (oldPosts) => - * oldPosts ? oldPosts.filter((post) => post.id !== deletedId) : oldPosts, - * ) - * ``` + * ```ts + * queryClient.setQueriesData({ queryKey: ['posts'] }, (oldPosts) => + * oldPosts ? oldPosts.filter((post) => post.id !== deletedId) : oldPosts, + * ) + * ``` + * + * @param filters - The filters that select which existing queries to update. + * @param updater - Either the new data, or a function that receives each + * matched query's current data (which may be `undefined`) and returns the + * new data. + * @param options - Set `updatedAt` to override the timestamp the written data + * is recorded with. + * @returns One `[queryKey, data]` tuple per matched query, in the same shape + * and with the same `undefined` case as {@link QueryClient#setQueryData}. */ setQueriesData< TQueryFnData, @@ -357,15 +386,18 @@ export class QueryClient { } /** - * Imperative (non-reactive) way to retrieve an existing query's state. If the query does not - * exist, `undefined` is returned. - * @param queryKey - The query key of the query to read. - * @returns The query's state, or `undefined` if no query with this key exists. + * Imperative (non-reactive) way to retrieve an existing query's state. If the + * query does not exist, `undefined` is returned. + * * @example - * ```ts - * const state = queryClient.getQueryState(['posts']) - * console.log(state?.dataUpdatedAt) - * ``` + * ```ts + * const state = queryClient.getQueryState(['posts']) + * console.log(state?.dataUpdatedAt) + * ``` + * + * @param queryKey - The query key of the query to read. + * @returns The query's state, or `undefined` if no query with this key + * exists. */ getQueryState< TQueryFnData = unknown, @@ -384,15 +416,17 @@ export class QueryClient { /** * Removes queries from the cache that match the given filters. Unlike - * {@link QueryClient#invalidateQueries} or {@link QueryClient#refetchQueries}, this removes - * matching queries from the cache instead of refetching them. Without filters, every query in - * the cache is removed. - * @param filters - The filters that select which queries to remove. Without filters, every query - * is removed. + * {@link QueryClient#invalidateQueries} or {@link QueryClient#refetchQueries}, + * this removes matching queries from the cache instead of refetching them. + * Without filters, every query in the cache is removed. + * * @example - * ```ts - * queryClient.removeQueries({ queryKey: ['posts'], exact: true }) - * ``` + * ```ts + * queryClient.removeQueries({ queryKey: ['posts'], exact: true }) + * ``` + * + * @param filters - The filters that select which queries to remove. Without + * filters, every query is removed. */ removeQueries( filters?: QueryFilters, @@ -406,18 +440,22 @@ export class QueryClient { } /** - * Resets queries matching the given filters back to their initial state (e.g. any - * `initialData`), notifying subscribers rather than removing them. Active queries among the - * matched set are then refetched, and the returned promise resolves once that refetch settles. - * @param filters - The filters that select which queries to reset. Without filters, every query - * is reset. - * @param options - Passed to the refetch of the active matched queries, e.g. `cancelRefetch` and - * `throwOnError`. - * @returns A promise that resolves once the refetch of the active matched queries settles. + * Resets queries matching the given filters back to their initial state (e.g. + * any `initialData`), notifying subscribers rather than removing them. Active + * queries among the matched set are then refetched, and the returned promise + * resolves once that refetch settles. + * * @example - * ```ts - * await queryClient.resetQueries({ queryKey: ['posts'], exact: true }) - * ``` + * ```ts + * await queryClient.resetQueries({ queryKey: ['posts'], exact: true }) + * ``` + * + * @param filters - The filters that select which queries to reset. Without + * filters, every query is reset. + * @param options - Passed to the refetch of the active matched queries, e.g. + * `cancelRefetch` and `throwOnError`. + * @returns A promise that resolves once the refetch of the active matched + * queries settles. */ resetQueries( filters?: QueryFilters, @@ -442,21 +480,24 @@ export class QueryClient { } /** - * Cancels outgoing fetches for queries matching the given filters. Most useful when performing - * optimistic updates, since any outgoing refetch that resolves afterwards would otherwise - * overwrite the optimistic update. By default (`revert: true`), a cancelled query's data is - * reverted to its state before the outgoing fetch started. + * Cancels outgoing fetches for queries matching the given filters. Most + * useful when performing optimistic updates, since any outgoing refetch that + * resolves afterwards would otherwise overwrite the optimistic update. By + * default (`revert: true`), a cancelled query's data is reverted to its state + * before the outgoing fetch started. * * The returned promise never rejects, even if individual cancellations fail. - * @param filters - The filters that select which queries to cancel. Without filters, every query - * is cancelled. - * @param cancelOptions - Passed to each matched query's cancellation. `revert` defaults to - * `true`. - * @returns A promise that resolves once every cancellation has settled. + * * @example - * ```ts - * await queryClient.cancelQueries({ queryKey: ['posts'], exact: true }) - * ``` + * ```ts + * await queryClient.cancelQueries({ queryKey: ['posts'], exact: true }) + * ``` + * + * @param filters - The filters that select which queries to cancel. Without + * filters, every query is cancelled. + * @param cancelOptions - Passed to each matched query's cancellation. + * `revert` defaults to `true`. + * @returns A promise that resolves once every cancellation has settled. */ cancelQueries( filters?: QueryFilters, @@ -477,19 +518,26 @@ export class QueryClient { * Marks queries matching the given filters as invalidated. Unlike * {@link QueryClient#removeQueries}, invalidated queries stay in the cache. * - * Unless `filters.refetchType` is `'none'`, matching queries are then refetched via - * {@link QueryClient#refetchQueries}, using `filters.refetchType` if set, otherwise - * `filters.type`, otherwise `'active'`. - * @param filters - The filters that select which queries to invalidate, plus `refetchType` to - * control which of them to refetch afterwards. Without filters, every query is invalidated. - * @param options - Passed to {@link QueryClient#refetchQueries}, e.g. `cancelRefetch` and - * `throwOnError`. - * @returns A promise that resolves once the refetch settles, or immediately if `refetchType` is - * `'none'`. + * Unless `filters.refetchType` is `'none'`, matching queries are then + * refetched via {@link QueryClient#refetchQueries}, using + * `filters.refetchType` if set, otherwise `filters.type`, otherwise + * `'active'`. + * * @example - * ```ts - * await queryClient.invalidateQueries({ queryKey: ['posts'], refetchType: 'active' }) - * ``` + * ```ts + * await queryClient.invalidateQueries({ + * queryKey: ['posts'], + * refetchType: 'active', + * }) + * ``` + * + * @param filters - The filters that select which queries to invalidate, plus + * `refetchType` to control which of them to refetch afterwards. Without + * filters, every query is invalidated. + * @param options - Passed to {@link QueryClient#refetchQueries}, e.g. + * `cancelRefetch` and `throwOnError`. + * @returns A promise that resolves once the refetch settles, or immediately + * if `refetchType` is `'none'`. */ invalidateQueries( filters?: InvalidateQueryFilters, @@ -514,23 +562,28 @@ export class QueryClient { } /** - * Refetches queries matching the given filters, regardless of whether they are stale. Without - * filters, every query in the cache is refetched. Queries that are disabled, or static (only - * have observers with a static `staleTime`), are never refetched. - * - * By default (`cancelRefetch: true`), a currently running fetch is cancelled before the new - * one starts. The returned promise resolves once all matching queries have settled; it does - * not reject on individual query failures unless `throwOnError` is set. - * @param filters - The filters that select which queries to refetch. Without filters, every query - * in the cache is included. - * @param options - Set `cancelRefetch` to `false` to keep a running fetch instead of cancelling - * it, and `throwOnError` to `true` to reject when a refetch fails. - * @returns A promise that resolves once every matched query has settled. + * Refetches queries matching the given filters, regardless of whether they + * are stale. Without filters, every query in the cache is refetched. Queries + * that are disabled, or static (only have observers with a static + * `staleTime`), are never refetched. + * + * By default (`cancelRefetch: true`), a currently running fetch is cancelled + * before the new one starts. The returned promise resolves once all matching + * queries have settled; it does not reject on individual query failures + * unless `throwOnError` is set. + * * @example - * ```ts - * // refetch all active queries partially matching a query key: - * await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' }) - * ``` + * ```ts + * // refetch all active queries partially matching a query key: + * await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' }) + * ``` + * + * @param filters - The filters that select which queries to refetch. Without + * filters, every query in the cache is included. + * @param options - Set `cancelRefetch` to `false` to keep a running fetch + * instead of cancelling it, and `throwOnError` to `true` to reject when a + * refetch fails. + * @returns A promise that resolves once every matched query has settled. */ refetchQueries( filters?: RefetchQueryFilters, @@ -559,38 +612,46 @@ export class QueryClient { } /** - * Asynchronous method to fetch and cache a query, resolving with the data or throwing with - * the error. - * - * If the query already exists in the cache and its data is not stale (per the given - * `staleTime`), the cached data is returned without fetching. Otherwise, the query is fetched - * and the promise resolves once the fetch settles. If a `select` function is provided, it is - * applied to the data in both cases (cached or freshly fetched) before it is returned. - * - * Unlike a reactive observer, retries are disabled by default here (`retry: false`) unless - * explicitly configured, since there is no component to catch a thrown error and retry through - * re-render. - * - * The accepted options are `QueryObserverOptions` minus the fields that only make sense for a - * reactive observer — `enabled`, `refetchInterval`, `refetchIntervalInBackground`, - * `refetchOnWindowFocus`, `refetchOnReconnect`, `refetchOnMount`, `retryOnMount`, - * `notifyOnChangeProps`, `throwOnError`, `suspense`, and `placeholderData` are not part of this - * method's options. - * - * This method replaces the deprecated `fetchQuery`, and — combined with - * `{ staleTime: 'static' }` — the deprecated `ensureQueryData`. - * @param options - The query options, including the `queryKey` and the `queryFn` used if the - * query needs to fetch. - * @returns A promise that resolves to the data, or to the result of `select` if provided. It - * rejects with the error from the fetch or from `select`. + * Asynchronous method to fetch and cache a query, resolving with the data or + * throwing with the error. + * + * If the query already exists in the cache and its data is not stale (per the + * given `staleTime`), the cached data is returned without fetching. + * Otherwise, the query is fetched and the promise resolves once the fetch + * settles. If a `select` function is provided, it is applied to the data in + * both cases (cached or freshly fetched) before it is returned. + * + * Unlike a reactive observer, retries are disabled by default here (`retry: + * false`) unless explicitly configured, since there is no component to catch + * a thrown error and retry through re-render. + * + * The accepted options are `QueryObserverOptions` minus the fields that only + * make sense for a reactive observer — `enabled`, `refetchInterval`, + * `refetchIntervalInBackground`, `refetchOnWindowFocus`, + * `refetchOnReconnect`, `refetchOnMount`, `retryOnMount`, + * `notifyOnChangeProps`, `throwOnError`, `suspense`, and `placeholderData` + * are not part of this method's options. + * + * This method replaces the deprecated `fetchQuery`, and — combined with `{ + * staleTime: 'static' }` — the deprecated `ensureQueryData`. + * * @example - * ```ts - * try { - * const data = await queryClient.query({ queryKey, queryFn, staleTime: 10000 }) - * } catch (error) { - * console.log(error) - * } - * ``` + * ```ts + * try { + * const data = await queryClient.query({ + * queryKey, + * queryFn, + * staleTime: 10000, + * }) + * } catch (error) { + * console.log(error) + * } + * ``` + * + * @param options - The query options, including the `queryKey` and the + * `queryFn` used if the query needs to fetch. + * @returns A promise that resolves to the data, or to the result of `select` + * if provided. It rejects with the error from the fetch or from `select`. */ async query< TQueryFnData, @@ -636,13 +697,15 @@ export class QueryClient { } /** - * Fetches and caches a query, or returns its cached data if it isn't stale. Unlike in observers, - * the fetch isn't retried unless `retry` is set. - * @param options - The query options, including the `queryKey` and the `queryFn` used if the - * query needs to fetch. - * @returns A promise that resolves to the cached or fetched data, or rejects with the fetch - * error. - * @deprecated Use queryClient.query(options) instead. This method will be removed in the next major version. + * Fetches and caches a query, or returns its cached data if it isn't stale. + * Unlike in observers, the fetch isn't retried unless `retry` is set. + * + * @deprecated Use queryClient.query(options) instead. This method will be + * removed in the next major version. + * @param options - The query options, including the `queryKey` and the + * `queryFn` used if the query needs to fetch. + * @returns A promise that resolves to the cached or fetched data, or rejects + * with the fetch error. */ fetchQuery< TQueryFnData, @@ -676,12 +739,15 @@ export class QueryClient { } /** - * Fetches and caches a query like {@link QueryClient#fetchQuery}, but ignores the result and any - * error. - * @param options - The query options, including the `queryKey` and the `queryFn` used if the - * query needs to fetch. + * Fetches and caches a query like {@link QueryClient#fetchQuery}, but ignores + * the result and any error. + * + * @deprecated Use queryClient.query(options) instead. You can swallow errors + * with `.catch(noop)`. This method will be removed in the next major + * version. + * @param options - The query options, including the `queryKey` and the + * `queryFn` used if the query needs to fetch. * @returns A promise that resolves once the fetch settles. It never rejects. - * @deprecated Use queryClient.query(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. */ prefetchQuery< TQueryFnData = unknown, @@ -700,24 +766,32 @@ export class QueryClient { * {@link InfiniteData} object or throwing with the error. * * Behaves like {@link QueryClient#query}, accepting the same options (minus - * `initialPageParam`), plus the required `initialPageParam`, and an optional `pages` / - * `getNextPageParam` pair used to refetch a fixed number of pages from the start. - * - * This method replaces the deprecated `fetchInfiniteQuery`, and — combined with - * `{ staleTime: 'static' }` — the deprecated `ensureInfiniteQueryData`. - * @param options - The infinite query options, including the `queryKey`, the `queryFn`, and the - * `initialPageParam`. - * @returns A promise that resolves to the {@link InfiniteData}, or to the result of `select` if - * provided. It rejects with the error from the fetch or from `select`. + * `initialPageParam`), plus the required `initialPageParam`, and an optional + * `pages` / `getNextPageParam` pair used to refetch a fixed number of pages + * from the start. + * + * This method replaces the deprecated `fetchInfiniteQuery`, and — combined + * with `{ staleTime: 'static' }` — the deprecated `ensureInfiniteQueryData`. + * * @example - * ```ts - * try { - * const data = await queryClient.infiniteQuery({ queryKey, queryFn, initialPageParam: 0 }) - * console.log(data.pages) - * } catch (error) { - * console.log(error) - * } - * ``` + * ```ts + * try { + * const data = await queryClient.infiniteQuery({ + * queryKey, + * queryFn, + * initialPageParam: 0, + * }) + * console.log(data.pages) + * } catch (error) { + * console.log(error) + * } + * ``` + * + * @param options - The infinite query options, including the `queryKey`, the + * `queryFn`, and the `initialPageParam`. + * @returns A promise that resolves to the {@link InfiniteData}, or to the + * result of `select` if provided. It rejects with the error from the fetch + * or from `select`. */ infiniteQuery< TQueryFnData, @@ -743,12 +817,15 @@ export class QueryClient { } /** - * Fetches and caches an infinite query, or returns its cached data if it isn't stale. - * @param options - The infinite query options, including the `queryKey`, the `queryFn`, and the - * `initialPageParam`. - * @returns A promise that resolves to the cached or fetched {@link InfiniteData}, or rejects with - * the fetch error. - * @deprecated Use queryClient.infiniteQuery(options) instead. This method will be removed in the next major version. + * Fetches and caches an infinite query, or returns its cached data if it + * isn't stale. + * + * @deprecated Use queryClient.infiniteQuery(options) instead. This method + * will be removed in the next major version. + * @param options - The infinite query options, including the `queryKey`, the + * `queryFn`, and the `initialPageParam`. + * @returns A promise that resolves to the cached or fetched + * {@link InfiniteData}, or rejects with the fetch error. */ fetchInfiniteQuery< TQueryFnData, @@ -771,12 +848,16 @@ export class QueryClient { } /** - * Fetches and caches an infinite query like {@link QueryClient#fetchInfiniteQuery}, but ignores - * the result and any error. - * @param options - The infinite query options, including the `queryKey`, the `queryFn`, and the - * `initialPageParam`. + * Fetches and caches an infinite query like + * {@link QueryClient#fetchInfiniteQuery}, but ignores the result and any + * error. + * + * @deprecated Use queryClient.infiniteQuery(options) instead. You can swallow + * errors with `.catch(noop)`. This method will be removed in the next major + * version. + * @param options - The infinite query options, including the `queryKey`, the + * `queryFn`, and the `initialPageParam`. * @returns A promise that resolves once the fetch settles. It never rejects. - * @deprecated Use queryClient.infiniteQuery(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. */ prefetchInfiniteQuery< TQueryFnData, @@ -798,13 +879,16 @@ export class QueryClient { } /** - * Returns the cached data of an infinite query, or fetches it if there is none. With - * `revalidateIfStale`, stale cached data is also refetched in the background. - * @param options - The infinite query options. If the query has no cached data yet, it is fetched - * with these options. - * @returns A promise that resolves to the cached {@link InfiniteData}, or to the fetched data if - * nothing was cached yet. - * @deprecated Use queryClient.infiniteQuery({ ...options, staleTime: 'static' }) instead. This method will be removed in the next major version. + * Returns the cached data of an infinite query, or fetches it if there is + * none. With `revalidateIfStale`, stale cached data is also refetched in the + * background. + * + * @deprecated Use queryClient.infiniteQuery({ ...options, staleTime: 'static' + * }) instead. This method will be removed in the next major version. + * @param options - The infinite query options. If the query has no cached + * data yet, it is fetched with these options. + * @returns A promise that resolves to the cached {@link InfiniteData}, or to + * the fetched data if nothing was cached yet. */ ensureInfiniteQueryData< TQueryFnData, @@ -828,16 +912,18 @@ export class QueryClient { } /** - * Resumes mutations that were paused because there was no network connection. Does nothing - * (resolving immediately) if the client is currently offline. - * @returns A promise that resolves once the resumed mutations have settled. + * Resumes mutations that were paused because there was no network connection. + * Does nothing (resolving immediately) if the client is currently offline. + * * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' + * ```ts + * import { QueryClient } from '@tanstack/query-core' + * + * const queryClient = new QueryClient() + * await queryClient.resumePausedMutations() + * ``` * - * const queryClient = new QueryClient() - * await queryClient.resumePausedMutations() - * ``` + * @returns A promise that resolves once the resumed mutations have settled. */ resumePausedMutations(): Promise { if (onlineManager.isOnline()) { @@ -848,15 +934,17 @@ export class QueryClient { /** * Returns the query cache this client is connected to. - * @returns The {@link QueryCache} instance. + * * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' + * ```ts + * import { QueryClient } from '@tanstack/query-core' * - * const queryClient = new QueryClient() - * const queryCache = queryClient.getQueryCache() - * const queries = queryCache.findAll({ queryKey: ['posts'] }) - * ``` + * const queryClient = new QueryClient() + * const queryCache = queryClient.getQueryCache() + * const queries = queryCache.findAll({ queryKey: ['posts'] }) + * ``` + * + * @returns The {@link QueryCache} instance. */ getQueryCache(): QueryCache { return this.#queryCache @@ -864,15 +952,17 @@ export class QueryClient { /** * Returns the mutation cache this client is connected to. - * @returns The {@link MutationCache} instance. + * * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' + * ```ts + * import { QueryClient } from '@tanstack/query-core' + * + * const queryClient = new QueryClient() + * const mutationCache = queryClient.getMutationCache() + * const mutations = mutationCache.findAll({ status: 'pending' }) + * ``` * - * const queryClient = new QueryClient() - * const mutationCache = queryClient.getMutationCache() - * const mutations = mutationCache.findAll({ status: 'pending' }) - * ``` + * @returns The {@link MutationCache} instance. */ getMutationCache(): MutationCache { return this.#mutationCache @@ -881,55 +971,64 @@ export class QueryClient { /** * Returns the default options that were set when creating the client, or via * {@link QueryClient#setDefaultOptions}. - * @returns The client's current default options. + * * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' + * ```ts + * import { QueryClient } from '@tanstack/query-core' * - * const queryClient = new QueryClient() - * const defaultOptions = queryClient.getDefaultOptions() - * ``` + * const queryClient = new QueryClient() + * const defaultOptions = queryClient.getDefaultOptions() + * ``` + * + * @returns The client's current default options. */ getDefaultOptions(): DefaultOptions { return this.#defaultOptions } /** - * Dynamically sets the default options for this client, overwriting any previously defined - * default options. + * Dynamically sets the default options for this client, overwriting any + * previously defined default options. + * + * @example + * ```ts + * import { QueryClient } from '@tanstack/query-core' + * + * const queryClient = new QueryClient() + * queryClient.setDefaultOptions({ + * queries: { + * staleTime: Infinity, + * }, + * }) + * ``` + * * @param options - The new default options for queries and mutations. * @see {@link QueryClient#getDefaultOptions} - * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' - * - * const queryClient = new QueryClient() - * queryClient.setDefaultOptions({ - * queries: { - * staleTime: Infinity, - * }, - * }) - * ``` */ setDefaultOptions(options: DefaultOptions): void { this.#defaultOptions = options } /** - * Sets default options for queries whose query key partially matches the given `queryKey`. + * Sets default options for queries whose query key partially matches the + * given `queryKey`. + * + * If several registered query defaults match a given query key, they are + * merged together in registration order by + * {@link QueryClient#getQueryDefaults}, so register defaults from the most + * generic key to the least generic one — more specific defaults should be + * registered after more generic ones so they take precedence. * - * If several registered query defaults match a given query key, they are merged together in - * registration order by {@link QueryClient#getQueryDefaults}, so register defaults from the - * most generic key to the least generic one — more specific defaults should be registered - * after more generic ones so they take precedence. - * @param queryKey - The query key that query keys are partially matched against. - * @param options - The default options applied to matching queries. * @example - * ```ts - * queryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts }) + * ```ts + * queryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts }) + * + * await queryClient.query({ queryKey: ['posts'] }) + * ``` * - * await queryClient.query({ queryKey: ['posts'] }) - * ``` + * @param queryKey - The query key that query keys are partially matched + * against. + * @param options - The default options applied to matching queries. */ setQueryDefaults< TQueryFnData = unknown, @@ -952,16 +1051,19 @@ export class QueryClient { } /** - * Returns the default options registered for queries whose query key partially matches the - * given `queryKey`, via {@link QueryClient#setQueryDefaults}. If multiple registered defaults - * match, they are merged together in registration order. - * @param queryKey - The query key to look up registered defaults for. - * @returns The merged default options of every registration that matches, or an empty object if - * none match. + * Returns the default options registered for queries whose query key + * partially matches the given `queryKey`, via + * {@link QueryClient#setQueryDefaults}. If multiple registered defaults match, + * they are merged together in registration order. + * * @example - * ```ts - * const defaultOptions = queryClient.getQueryDefaults(['posts']) - * ``` + * ```ts + * const defaultOptions = queryClient.getQueryDefaults(['posts']) + * ``` + * + * @param queryKey - The query key to look up registered defaults for. + * @returns The merged default options of every registration that matches, or + * an empty object if none match. */ getQueryDefaults( queryKey: QueryKey, @@ -982,16 +1084,20 @@ export class QueryClient { } /** - * Sets default options for mutations whose mutation key partially matches the given - * `mutationKey`. As with {@link QueryClient#setQueryDefaults}, the order of registration - * matters when several registered defaults match the same mutation key. - * @param mutationKey - The mutation key that mutation keys are partially matched against. + * Sets default options for mutations whose mutation key partially matches the + * given `mutationKey`. As with {@link QueryClient#setQueryDefaults}, the order + * of registration matters when several registered defaults match the same + * mutation key. + * + * @example + * ```ts + * queryClient.setMutationDefaults(['addPost'], { mutationFn: addPost }) + * ``` + * + * @param mutationKey - The mutation key that mutation keys are partially + * matched against. * @param options - The default options applied to matching mutations. * @see {@link QueryClient#getMutationDefaults} - * @example - * ```ts - * queryClient.setMutationDefaults(['addPost'], { mutationFn: addPost }) - * ``` */ setMutationDefaults< TData = unknown, @@ -1012,16 +1118,19 @@ export class QueryClient { } /** - * Returns the default options registered for mutations whose mutation key partially matches - * the given `mutationKey`, via {@link QueryClient#setMutationDefaults}. If multiple registered - * defaults match, they are merged together in registration order. - * @param mutationKey - The mutation key to look up registered defaults for. - * @returns The merged default options of every registration that matches, or an empty object if - * none match. + * Returns the default options registered for mutations whose mutation key + * partially matches the given `mutationKey`, via + * {@link QueryClient#setMutationDefaults}. If multiple registered defaults + * match, they are merged together in registration order. + * * @example - * ```ts - * const defaultOptions = queryClient.getMutationDefaults(['addPost']) - * ``` + * ```ts + * const defaultOptions = queryClient.getMutationDefaults(['addPost']) + * ``` + * + * @param mutationKey - The mutation key to look up registered defaults for. + * @returns The merged default options of every registration that matches, or + * an empty object if none match. */ getMutationDefaults( mutationKey: MutationKey, @@ -1043,13 +1152,15 @@ export class QueryClient { } /** - * Called by framework adapters (e.g. inside `useQuery`) to resolve the options passed by the - * caller into their final, defaulted form: merging the client's own `defaultOptions.queries`, - * then `queryClient.setQueryDefaults` for the given `queryKey`, then the caller's options on - * top. A no-op if the options are already defaulted (`_defaulted: true`). + * Called by framework adapters (e.g. inside `useQuery`) to resolve the + * options passed by the caller into their final, defaulted form: merging the + * client's own `defaultOptions.queries`, then `queryClient.setQueryDefaults` + * for the given `queryKey`, then the caller's options on top. A no-op if the + * options are already defaulted (`_defaulted: true`). + * * @param options - The query options passed by the caller. - * @returns The defaulted options, with `queryHash` and dependent defaults (e.g. - * `refetchOnReconnect`) filled in. + * @returns The defaulted options, with `queryHash` and dependent defaults + * (e.g. `refetchOnReconnect`) filled in. */ defaultQueryOptions< TQueryFnData = unknown, @@ -1133,10 +1244,12 @@ export class QueryClient { } /** - * The mutation counterpart of {@link QueryClient#defaultQueryOptions}. Called by framework - * adapters (e.g. inside `useMutation`) to merge the client's `defaultOptions.mutations`, then - * `queryClient.setMutationDefaults` for the given `mutationKey`, then the caller's options on - * top. A no-op if the options are already defaulted (`_defaulted: true`). + * The mutation counterpart of {@link QueryClient#defaultQueryOptions}. Called + * by framework adapters (e.g. inside `useMutation`) to merge the client's + * `defaultOptions.mutations`, then `queryClient.setMutationDefaults` for the + * given `mutationKey`, then the caller's options on top. A no-op if the + * options are already defaulted (`_defaulted: true`). + * * @param options - The mutation options passed by the caller. * @returns The defaulted options. */ @@ -1156,14 +1269,16 @@ export class QueryClient { } /** - * Clears both the query cache and the mutation cache this client is connected to. + * Clears both the query cache and the mutation cache this client is connected + * to. + * * @example - * ```ts - * import { QueryClient } from '@tanstack/query-core' + * ```ts + * import { QueryClient } from '@tanstack/query-core' * - * const queryClient = new QueryClient() - * queryClient.clear() - * ``` + * const queryClient = new QueryClient() + * queryClient.clear() + * ``` */ clear(): void { this.#queryCache.clear() diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts index 8afad2c3898..3391a7aac21 100644 --- a/packages/query-core/src/queryObserver.ts +++ b/packages/query-core/src/queryObserver.ts @@ -37,21 +37,22 @@ interface ObserverFetchOptions extends FetchOptions { /** * A `QueryObserver` watches a single query in the `QueryCache` and computes a * `QueryObserverResult` from its state, recomputing and notifying subscribers - * whenever the underlying query (or the observer's options) changes. It is - * the primitive that framework adapters (e.g. `useQuery`) build their hooks - * on top of, but it can also be used directly to observe and switch between - * queries outside of any framework. + * whenever the underlying query (or the observer's options) changes. It is the + * primitive that framework adapters (e.g. `useQuery`) build their hooks on top + * of, but it can also be used directly to observe and switch between queries + * outside of any framework. + * * @example - * ```ts - * const observer = new QueryObserver(queryClient, { - * queryKey: ['posts'], - * queryFn: fetchPosts, - * }) + * ```ts + * const observer = new QueryObserver(queryClient, { + * queryKey: ['posts'], + * queryFn: fetchPosts, + * }) * - * const unsubscribe = observer.subscribe((result) => { - * console.log(result.data) - * }) - * ``` + * const unsubscribe = observer.subscribe((result) => { + * console.log(result.data) + * }) + * ``` */ export class QueryObserver< TQueryFnData = unknown, @@ -103,8 +104,9 @@ export class QueryObserver< } /** - * Binds the methods of the result (`refetch`) to the observer, so they keep working when destructured - * from it. Subclasses override it to bind their own result methods as well. + * Binds the methods of the result (`refetch`) to the observer, so they keep + * working when destructured from it. Subclasses override it to bind their own + * result methods as well. */ protected bindMethods(): void { this.refetch = this.refetch.bind(this) @@ -131,9 +133,9 @@ export class QueryObserver< } /** - * Returns whether the observed query is currently stale and configured - * (via the `refetchOnReconnect` option) to refetch when the network - * reconnects. + * Returns whether the observed query is currently stale and configured (via + * the `refetchOnReconnect` option) to refetch when the network reconnects. + * * @returns `true` if the observer should refetch the query on reconnect. */ shouldFetchOnReconnect(): boolean { @@ -145,9 +147,10 @@ export class QueryObserver< } /** - * Returns whether the observed query is currently stale and configured - * (via the `refetchOnWindowFocus` option) to refetch when the window - * regains focus. + * Returns whether the observed query is currently stale and configured (via + * the `refetchOnWindowFocus` option) to refetch when the window regains + * focus. + * * @returns `true` if the observer should refetch the query on window focus. */ shouldFetchOnWindowFocus(): boolean { @@ -159,9 +162,9 @@ export class QueryObserver< } /** - * Stops observing the current query: clears all listeners, cancels the - * stale and refetch-interval timers, and removes this observer from the - * query it was observing. + * Stops observing the current query: clears all listeners, cancels the stale + * and refetch-interval timers, and removes this observer from the query it + * was observing. */ destroy(): void { this.listeners = new Set() @@ -176,15 +179,24 @@ export class QueryObserver< * trigger a fetch if the new options require one and the observer has * subscribers, recompute the current result, and reschedule the stale and * refetch-interval timers as needed. - * @param options - The new observer options. They are defaulted with {@link - * QueryClient#defaultQueryOptions} before being applied. - * @throws {Error} If `enabled` is neither a boolean nor a function. + * * @example - * ```ts - * observer.setOptions({ queryKey: ['posts', 1], queryFn: () => fetchPost(1) }) - * // later: switch to a different query, reusing the same observer - * observer.setOptions({ queryKey: ['posts', 2], queryFn: () => fetchPost(2) }) - * ``` + * ```ts + * observer.setOptions({ + * queryKey: ['posts', 1], + * queryFn: () => fetchPost(1), + * }) + * // later: switch to a different query, reusing the same observer + * observer.setOptions({ + * queryKey: ['posts', 2], + * queryFn: () => fetchPost(2), + * }) + * ``` + * + * @param options - The new observer options. They are defaulted with + * {@link + * QueryClient#defaultQueryOptions} before being applied. + * @throws {Error} If `enabled` is neither a boolean nor a function. */ setOptions( options: QueryObserverOptions< @@ -271,10 +283,13 @@ export class QueryObserver< } /** - * Computes the result the observer would produce for the given (already-defaulted) options - * right now, building the underlying `Query` if it doesn't exist yet, without waiting for a - * subscription callback. Called by framework adapters on every render (e.g. `useQuery`) so the - * returned value is available synchronously, ahead of `setOptions` triggering an actual fetch. + * Computes the result the observer would produce for the given + * (already-defaulted) options right now, building the underlying `Query` if + * it doesn't exist yet, without waiting for a subscription callback. Called + * by framework adapters on every render (e.g. `useQuery`) so the returned + * value is available synchronously, ahead of `setOptions` triggering an + * actual fetch. + * * @param options - The defaulted observer options to compute the result for. * @returns The result for the given options. */ @@ -316,26 +331,30 @@ export class QueryObserver< } /** - * Returns the most recently computed `QueryObserverResult` for the - * observed query. This is a point-in-time read; to be notified of updates - * as they happen, subscribe to the observer instead (its inherited - * `subscribe` method). - * @returns The observer's latest result. + * Returns the most recently computed `QueryObserverResult` for the observed + * query. This is a point-in-time read; to be notified of updates as they + * happen, subscribe to the observer instead (its inherited `subscribe` + * method). + * * @example - * ```ts - * const result = observer.getCurrentResult() - * console.log(result.status, result.data) - * ``` + * ```ts + * const result = observer.getCurrentResult() + * console.log(result.status, result.data) + * ``` + * + * @returns The observer's latest result. */ getCurrentResult(): QueryObserverResult { return this.#currentResult } /** - * Wraps a `QueryObserverResult` in a `Proxy` that records which properties are read, via - * {@link QueryObserver#trackProp} (and an optional `onPropTracked` callback). Used by framework - * adapters when `notifyOnChangeProps` is not set, to implement its default "only re-render on - * properties you actually read" behavior. + * Wraps a `QueryObserverResult` in a `Proxy` that records which properties + * are read, via {@link QueryObserver#trackProp} (and an optional + * `onPropTracked` callback). Used by framework adapters when + * `notifyOnChangeProps` is not set, to implement its default "only re-render + * on properties you actually read" behavior. + * * @param result - The result to wrap. * @param onPropTracked - Called with the name of each property that is read. * @returns A proxy of `result` that tracks property reads. @@ -354,10 +373,13 @@ export class QueryObserver< } /** - * Records that the given `QueryObserverResult` property was read, so a subsequent update only - * notifies this observer if a tracked property actually changed. Normally called indirectly via - * {@link QueryObserver#trackResult}'s proxy; exposed directly for adapters that track property - * access themselves (e.g. through their own reactivity system) instead of via the proxy. + * Records that the given `QueryObserverResult` property was read, so a + * subsequent update only notifies this observer if a tracked property + * actually changed. Normally called indirectly via + * {@link QueryObserver#trackResult}'s proxy; exposed directly for adapters + * that track property access themselves (e.g. through their own reactivity + * system) instead of via the proxy. + * * @param key - The name of the property that was read. */ trackProp(key: keyof QueryObserverResult) { @@ -366,6 +388,7 @@ export class QueryObserver< /** * Returns the `Query` instance this observer is currently observing. + * * @returns The observed query. */ getCurrentQuery(): Query { @@ -373,16 +396,19 @@ export class QueryObserver< } /** - * Refetches the observed query and returns a promise that resolves with - * the resulting `QueryObserverResult`. - * @param options - Set `cancelRefetch` to `false` to keep a running fetch instead of cancelling - * it, and `throwOnError` to `true` to reject when the refetch fails. - * @returns A promise that resolves with the result after the refetch. + * Refetches the observed query and returns a promise that resolves with the + * resulting `QueryObserverResult`. + * * @example - * ```ts - * const result = await observer.refetch({ cancelRefetch: false }) - * console.log(result.data) - * ``` + * ```ts + * const result = await observer.refetch({ cancelRefetch: false }) + * console.log(result.data) + * ``` + * + * @param options - Set `cancelRefetch` to `false` to keep a running fetch + * instead of cancelling it, and `throwOnError` to `true` to reject when the + * refetch fails. + * @returns A promise that resolves with the result after the refetch. */ refetch({ ...options }: RefetchOptions = {}): Promise< QueryObserverResult @@ -394,20 +420,22 @@ export class QueryObserver< /** * Fetches a query defined by the given options without affecting this - * observer's own tracked query or result, and returns a promise that - * resolves with the `QueryObserverResult` for that fetch. This is useful - * for prefetching data that another observer (e.g. a query about to be - * navigated to) will need, ahead of time. + * observer's own tracked query or result, and returns a promise that resolves + * with the `QueryObserverResult` for that fetch. This is useful for + * prefetching data that another observer (e.g. a query about to be navigated + * to) will need, ahead of time. + * + * @example + * ```ts + * const result = await observer.fetchOptimistic({ + * queryKey: ['posts', 2], + * queryFn: () => fetchPost(2), + * }) + * console.log(result.data) + * ``` + * * @param options - The observer options of the query to fetch. * @returns A promise that resolves with the result for the fetched query. - * @example - * ```ts - * const result = await observer.fetchOptimistic({ - * queryKey: ['posts', 2], - * queryFn: () => fetchPost(2), - * }) - * console.log(result.data) - * ``` */ fetchOptimistic( options: QueryObserverOptions< @@ -463,9 +491,11 @@ export class QueryObserver< } /** - * Fetches the observed query and updates the result once the fetch settles. Used by `refetch` and, - * in `InfiniteQueryObserver`, to fetch more pages. - * @param fetchOptions - Options for this fetch. `cancelRefetch` defaults to `true`. + * Fetches the observed query and updates the result once the fetch settles. + * Used by `refetch` and, in `InfiniteQueryObserver`, to fetch more pages. + * + * @param fetchOptions - Options for this fetch. `cancelRefetch` defaults to + * `true`. * @returns A promise that resolves with the updated result. */ protected fetch( @@ -580,8 +610,10 @@ export class QueryObserver< } /** - * Computes the result for a query and options from the query's state, applying `select`, - * `placeholderData`, and the derived flags. Subclasses override it to add their own fields. + * Computes the result for a query and options from the query's state, + * applying `select`, `placeholderData`, and the derived flags. Subclasses + * override it to add their own fields. + * * @param query - The query to compute the result for. * @param options - The observer options to compute the result with. * @returns The computed result. @@ -758,9 +790,10 @@ export class QueryObserver< } /** - * Recomputes and stores the current result from the current query/options, notifying listeners - * if it changed. Framework adapters call this right after subscribing to make sure no query - * update was missed in the gap between creating the observer and subscribing to it. + * Recomputes and stores the current result from the current query/options, + * notifying listeners if it changed. Framework adapters call this right after + * subscribing to make sure no query update was missed in the gap between + * creating the observer and subscribing to it. */ updateResult(): void { const prevResult = this.#currentResult as @@ -855,8 +888,9 @@ export class QueryObserver< } /** - * Updates the observer's result when the observed query changes, and reschedules its timers if it - * has listeners. + * Updates the observer's result when the observed query changes, and + * reschedules its timers if it has listeners. + * * @internal */ onQueryUpdate(): void { @@ -869,11 +903,13 @@ export class QueryObserver< } /** - * Checks whether a query has no data yet and should do its initial load when an observer mounts. + * Checks whether a query has no data yet and should do its initial load when an + * observer mounts. + * * @param query - The query to check. * @param options - The observer options. - * @returns `true` if the query is enabled, has no data, and isn't in an error state with - * `retryOnMount: false`. + * @returns `true` if the query is enabled, has no data, and isn't in an error + * state with `retryOnMount: false`. */ function shouldLoadOnMount( query: Query, @@ -890,8 +926,10 @@ function shouldLoadOnMount( } /** - * Checks whether a query should fetch when an observer mounts: either for its initial load, or - * because it has data and `refetchOnMount` asks for a refetch. + * Checks whether a query should fetch when an observer mounts: either for its + * initial load, or because it has data and `refetchOnMount` asks for a + * refetch. + * * @param query - The query to check. * @param options - The observer options. * @returns `true` if the query should fetch on mount. @@ -908,13 +946,14 @@ function shouldFetchOnMount( } /** - * Checks whether a query should fetch for a `refetchOnMount`, `refetchOnWindowFocus`, or - * `refetchOnReconnect` option. + * Checks whether a query should fetch for a `refetchOnMount`, + * `refetchOnWindowFocus`, or `refetchOnReconnect` option. + * * @param query - The query to check. * @param options - The observer options. * @param field - The value of the option to check. - * @returns `true` if the query is enabled, not static, and the option is `'always'`, or is not - * `false` and the query is stale. + * @returns `true` if the query is enabled, not static, and the option is + * `'always'`, or is not `false` and the query is stale. */ function shouldFetchOn( query: Query, @@ -936,12 +975,13 @@ function shouldFetchOn( /** * Checks whether a query should fetch after the observer's options change. + * * @param query - The query observed with the new options. * @param prevQuery - The query observed with the previous options. * @param options - The new observer options. * @param prevOptions - The previous observer options. - * @returns `true` if the query changed or was disabled before, it isn't a suspense query in an - * error state, and it is stale. + * @returns `true` if the query changed or was disabled before, it isn't a + * suspense query in an error state, and it is stale. */ function shouldFetchOptionally( query: Query, @@ -959,9 +999,12 @@ function shouldFetchOptionally( /** * Checks whether a query is stale for the given observer options. + * * @param query - The query to check. - * @param options - The observer options, whose `enabled` and `staleTime` are used. - * @returns `true` if the query is enabled and its data is stale for `staleTime`. + * @param options - The observer options, whose `enabled` and `staleTime` are + * used. + * @returns `true` if the query is enabled and its data is stale for + * `staleTime`. */ function isStale( query: Query, diff --git a/packages/query-core/src/removable.ts b/packages/query-core/src/removable.ts index 573a19c684f..f77fdd89568 100644 --- a/packages/query-core/src/removable.ts +++ b/packages/query-core/src/removable.ts @@ -4,25 +4,27 @@ import { isValidTimeout } from './utils' import type { ManagedTimerId } from './timeoutManager' /** - * The base class for cache entries that are garbage collected once nothing is using them — - * `Query` and `Mutation` both extend it. `gcTime` controls how long an unused entry is kept. + * The base class for cache entries that are garbage collected once nothing is + * using them — `Query` and `Mutation` both extend it. `gcTime` controls how + * long an unused entry is kept. */ export abstract class Removable { gcTime!: number #gcTimeout?: ManagedTimerId /** - * Clears the pending garbage collection timeout, so the entry is no longer scheduled for removal. - * A subclass may override this to release what it holds on to as well — `Query` also cancels any - * in-flight fetch. + * Clears the pending garbage collection timeout, so the entry is no longer + * scheduled for removal. A subclass may override this to release what it + * holds on to as well — `Query` also cancels any in-flight fetch. */ destroy(): void { this.clearGcTimeout() } /** - * Schedules the entry to be removed from its cache after `gcTime`, replacing any timeout scheduled - * before. Nothing is scheduled if `gcTime` is `Infinity`. + * Schedules the entry to be removed from its cache after `gcTime`, replacing + * any timeout scheduled before. Nothing is scheduled if `gcTime` is + * `Infinity`. */ protected scheduleGc(): void { this.clearGcTimeout() @@ -35,8 +37,9 @@ export abstract class Removable { } /** - * Updates `gcTime`, keeping the longest one seen so far. Without a value, it defaults to 5 minutes - * on the client and `Infinity` on the server. + * Updates `gcTime`, keeping the longest one seen so far. Without a value, it + * defaults to 5 minutes on the client and `Infinity` on the server. + * * @param newGcTime - The `gcTime` from the latest options, if any. */ protected updateGcTime(newGcTime: number | undefined): void { @@ -47,9 +50,7 @@ export abstract class Removable { ) } - /** - * Cancels the scheduled removal, if there is one. - */ + /** Cancels the scheduled removal, if there is one. */ protected clearGcTimeout() { if (this.#gcTimeout !== undefined) { timeoutManager.clearTimeout(this.#gcTimeout) @@ -58,8 +59,9 @@ export abstract class Removable { } /** - * Called when the garbage collection timeout fires. Subclasses remove the entry from its cache - * unless it is still in use, e.g. because it has observers. + * Called when the garbage collection timeout fires. Subclasses remove the + * entry from its cache unless it is still in use, e.g. because it has + * observers. */ protected abstract optionalRemove(): void } diff --git a/packages/query-core/src/retryer.ts b/packages/query-core/src/retryer.ts index e8c855db410..d16f58e3db0 100644 --- a/packages/query-core/src/retryer.ts +++ b/packages/query-core/src/retryer.ts @@ -20,42 +20,31 @@ interface RetryerConfig { } /** - * Runs a function with retries, and can pause, continue, or cancel it. Queries and mutations use - * one for each fetch or execution. + * Runs a function with retries, and can pause, continue, or cancel it. Queries + * and mutations use one for each fetch or execution. */ export interface Retryer { /** - * The promise that resolves with the data, or rejects once retries are exhausted or it is - * cancelled. + * The promise that resolves with the data, or rejects once retries are + * exhausted or it is cancelled. */ promise: Promise - /** - * Cancels the run, rejecting `promise` with a `CancelledError`. - */ + /** Cancels the run, rejecting `promise` with a `CancelledError`. */ cancel: (cancelOptions?: CancelOptions) => void - /** - * Resumes a paused run, and returns `promise`. - */ + /** Resumes a paused run, and returns `promise`. */ continue: () => Promise - /** - * Stops further retries. The current attempt still finishes. - */ + /** Stops further retries. The current attempt still finishes. */ cancelRetry: () => void - /** - * Allows retries again after `cancelRetry`. - */ + /** Allows retries again after `cancelRetry`. */ continueRetry: () => void /** - * Returns whether the run can start now, based on the network mode and `canRun`. + * Returns whether the run can start now, based on the network mode and + * `canRun`. */ canStart: () => boolean - /** - * Starts the run, or waits until it can start, and returns `promise`. - */ + /** Starts the run, or waits until it can start, and returns `promise`. */ start: () => Promise - /** - * Returns whether `promise` is still pending, resolved, or rejected. - */ + /** Returns whether `promise` is still pending, resolved, or rejected. */ status: () => 'pending' | 'resolved' | 'rejected' } @@ -80,7 +69,9 @@ type RetryDelayFunction = ( ) => number /** - * The default `retryDelay`: doubles with every failure, starting at 1 second, up to 30 seconds. + * The default `retryDelay`: doubles with every failure, starting at 1 second, + * up to 30 seconds. + * * @param failureCount - The number of failures so far. * @returns The delay before the next retry, in milliseconds. */ @@ -90,8 +81,10 @@ function defaultRetryDelay(failureCount: number) { /** * Checks whether a fetch can run for the given network mode. + * * @param networkMode - The `networkMode` option. Defaults to `'online'`. - * @returns `true` if the network mode is not `'online'`, or if it is and the client is online. + * @returns `true` if the network mode is not `'online'`, or if it is and the + * client is online. */ export function canFetch(networkMode: NetworkMode | undefined): boolean { return (networkMode ?? 'online') === 'online' @@ -100,22 +93,25 @@ export function canFetch(networkMode: NetworkMode | undefined): boolean { } /** - * The error thrown by a `Retryer` (and surfaced to `query.promise`/`mutation`) when a fetch is cancelled, e.g. via - * `query.cancel()`. `revert`, if `true`, tells the caller to restore the state the query was in before the fetch - * started instead of surfacing the error. `silent`, if `true`, tells the caller to suppress this error and instead - * resolve with the promise of the fetch that triggered the cancellation. + * The error thrown by a `Retryer` (and surfaced to `query.promise`/`mutation`) + * when a fetch is cancelled, e.g. via `query.cancel()`. `revert`, if `true`, + * tells the caller to restore the state the query was in before the fetch + * started instead of surfacing the error. `silent`, if `true`, tells the caller + * to suppress this error and instead resolve with the promise of the fetch that + * triggered the cancellation. + * * @example - * ```ts - * query.cancel() + * ```ts + * query.cancel() * - * try { - * await query.promise - * } catch (error) { - * if (error instanceof CancelledError) { - * // the fetch was cancelled, e.g. via `query.cancel()` + * try { + * await query.promise + * } catch (error) { + * if (error instanceof CancelledError) { + * // the fetch was cancelled, e.g. via `query.cancel()` + * } * } - * } - * ``` + * ``` */ export class CancelledError extends Error { revert?: boolean @@ -129,22 +125,25 @@ export class CancelledError extends Error { /** * Checks whether a value is a `CancelledError`. + * + * @deprecated Use instanceof `CancelledError` instead. * @param value - The value to check. * @returns `true` if `value` is a `CancelledError`. - * @deprecated Use instanceof `CancelledError` instead. */ export function isCancelledError(value: any): value is CancelledError { return value instanceof CancelledError } /** - * Creates a retryer, which runs a function and retries it on failure according to the `retry` and - * `retryDelay` options. It pauses while the network mode doesn't allow fetching or `canRun` returns - * `false`, and can be cancelled. Queries and mutations use it to run their `queryFn` and - * `mutationFn`. - * @param config - The function to run, the retry options, and the callbacks for failures, pausing, - * continuing, and cancellation. - * @returns The retryer, whose `promise` settles with the result of the function. + * Creates a retryer, which runs a function and retries it on failure according + * to the `retry` and `retryDelay` options. It pauses while the network mode + * doesn't allow fetching or `canRun` returns `false`, and can be cancelled. + * Queries and mutations use it to run their `queryFn` and `mutationFn`. + * + * @param config - The function to run, the retry options, and the callbacks for + * failures, pausing, continuing, and cancellation. + * @returns The retryer, whose `promise` settles with the result of the + * function. */ export function createRetryer( config: RetryerConfig, diff --git a/packages/query-core/src/streamedQuery.ts b/packages/query-core/src/streamedQuery.ts index 4a2c59b948c..875a70c08f9 100644 --- a/packages/query-core/src/streamedQuery.ts +++ b/packages/query-core/src/streamedQuery.ts @@ -13,7 +13,9 @@ type BaseStreamedQueryParams = { ) => AsyncIterable | Promise> /** * Defines how refetches are handled. - * - `'reset'` (default): erases all data and puts the query back into `pending` state. + * + * - `'reset'` (default): erases all data and puts the query back into `pending` + * state. * - `'append'`: appends new data to the existing data. * - `'replace'`: writes all data to the cache once the stream ends. */ @@ -34,13 +36,14 @@ type ReducibleStreamedQueryParams< TQueryKey extends QueryKey, > = BaseStreamedQueryParams & { /** - * Reduces streamed chunks into the final data shape. Required whenever `TData` is not an - * array, since there is no default way to accumulate non-array chunks. + * Reduces streamed chunks into the final data shape. Required whenever + * `TData` is not an array, since there is no default way to accumulate + * non-array chunks. */ reducer: (acc: TData, chunk: TQueryFnData) => TData /** - * The value used while the first chunk is being fetched, and returned if the stream yields no - * values. Required together with a custom `reducer`. + * The value used while the first chunk is being fetched, and returned if the + * stream yields no values. Required together with a custom `reducer`. */ initialValue: TData } @@ -50,22 +53,26 @@ type StreamedQueryParams = | ReducibleStreamedQueryParams /** - * This is a helper function to create a query function that streams data from an AsyncIterable. - * Data will be an Array of all the chunks received. - * The query will be in a 'pending' state until the first chunk of data is received, but will go to 'success' after that. - * The query will stay in fetchStatus 'fetching' until the stream ends. - * @param options - The `streamFn` that returns an AsyncIterable to stream data from, and the optional - * `refetchMode`, `reducer`, and `initialValue` options. - * @returns A query function to pass as `queryFn`. + * This is a helper function to create a query function that streams data from + * an AsyncIterable. Data will be an Array of all the chunks received. The query + * will be in a 'pending' state until the first chunk of data is received, but + * will go to 'success' after that. The query will stay in fetchStatus + * 'fetching' until the stream ends. + * * @example - * ```ts - * await queryClient.query({ - * queryKey: ['data'], - * queryFn: streamedQuery({ - * streamFn: fetchDataInChunks, - * }), - * }) - * ``` + * ```ts + * await queryClient.query({ + * queryKey: ['data'], + * queryFn: streamedQuery({ + * streamFn: fetchDataInChunks, + * }), + * }) + * ``` + * + * @param options - The `streamFn` that returns an AsyncIterable to stream data + * from, and the optional `refetchMode`, `reducer`, and `initialValue` + * options. + * @returns A query function to pass as `queryFn`. */ export function streamedQuery< TQueryFnData = unknown, diff --git a/packages/query-core/src/subscribable.ts b/packages/query-core/src/subscribable.ts index a0b9fc417de..b354793fbc3 100644 --- a/packages/query-core/src/subscribable.ts +++ b/packages/query-core/src/subscribable.ts @@ -1,6 +1,7 @@ /** - * The base class behind everything in Query that you can subscribe to: `QueryCache`, `MutationCache`, - * the observers, and the `FocusManager`/`OnlineManager` behind `focusManager` and `onlineManager`. + * The base class behind everything in Query that you can subscribe to: + * `QueryCache`, `MutationCache`, the observers, and the + * `FocusManager`/`OnlineManager` behind `focusManager` and `onlineManager`. * Subclasses decide what a listener receives and when it is called. */ export class Subscribable { @@ -11,19 +12,23 @@ export class Subscribable { } /** - * Registers a listener to be called on every update this object notifies about. Returns a function - * that removes the listener again — call it to stop listening. The base class never drops a listener - * on its own, though some subclasses clear all of theirs in `destroy()`. - * @param listener - Called on each update, with whatever the subclass passes to its subscribers. - * @returns A function that removes the listener. + * Registers a listener to be called on every update this object notifies + * about. Returns a function that removes the listener again — call it to stop + * listening. The base class never drops a listener on its own, though some + * subclasses clear all of theirs in `destroy()`. + * * @example - * ```ts - * const unsubscribe = subscribable.subscribe(() => { - * // react to the update - * }) + * ```ts + * const unsubscribe = subscribable.subscribe(() => { + * // react to the update + * }) + * + * unsubscribe() + * ``` * - * unsubscribe() - * ``` + * @param listener - Called on each update, with whatever the subclass passes + * to its subscribers. + * @returns A function that removes the listener. */ subscribe(listener: TListener): () => void { this.listeners.add(listener) @@ -37,7 +42,9 @@ export class Subscribable { } /** - * Returns `true` while at least one listener is registered, `false` once they have all unsubscribed. + * Returns `true` while at least one listener is registered, `false` once they + * have all unsubscribed. + * * @returns `true` if at least one listener is registered. */ hasListeners(): boolean { @@ -45,16 +52,17 @@ export class Subscribable { } /** - * Called after a listener is added. Does nothing here; subclasses override it, e.g. to start - * tracking what they observe once the first listener subscribes. + * Called after a listener is added. Does nothing here; subclasses override + * it, e.g. to start tracking what they observe once the first listener + * subscribes. */ protected onSubscribe(): void { // Do nothing } /** - * Called after a listener is removed. Does nothing here; subclasses override it, e.g. to clean up - * once the last listener unsubscribes. + * Called after a listener is removed. Does nothing here; subclasses override + * it, e.g. to clean up once the last listener unsubscribes. */ protected onUnsubscribe(): void { // Do nothing diff --git a/packages/query-core/src/timeoutManager.ts b/packages/query-core/src/timeoutManager.ts index adf349fb4fb..147cb67d80d 100644 --- a/packages/query-core/src/timeoutManager.ts +++ b/packages/query-core/src/timeoutManager.ts @@ -2,9 +2,9 @@ * {@link TimeoutManager} does not support passing arguments to the callback. * * `(_: void)` is the argument type inferred by TypeScript's default typings for - * `setTimeout(cb, number)`. - * If we don't accept a single void argument, then - * `new Promise(resolve => timeoutManager.setTimeout(resolve, N))` is a type error. + * `setTimeout(cb, number)`. If we don't accept a single void argument, then + * `new Promise(resolve => timeoutManager.setTimeout(resolve, N))` is a type + * error. */ export type TimeoutCallback = (_: void) => void @@ -19,30 +19,29 @@ export type ManagedTimerId = number | { [Symbol.toPrimitive]: () => number } /** * Backend for timer functions. * - * Timers are performance-sensitive: short-lived timers (delays under a few seconds) tend to be - * latency-sensitive, while long-lived ones may benefit more from coalescing — batching timers - * with similar deadlines together — which the default provider (backed by the platform's global - * `setTimeout`/`setInterval`) does not do. A custom provider can implement coalescing, and can - * also support delays longer than the ~24-day maximum of the global `setTimeout`. + * Timers are performance-sensitive: short-lived timers (delays under a few + * seconds) tend to be latency-sensitive, while long-lived ones may benefit more + * from coalescing — batching timers with similar deadlines together — which the + * default provider (backed by the platform's global `setTimeout`/`setInterval`) + * does not do. A custom provider can implement coalescing, and can also support + * delays longer than the ~24-day maximum of the global `setTimeout`. */ export type TimeoutProvider = { /** - * Schedules `callback` to run once after `delay` milliseconds, like the global `setTimeout`. + * Schedules `callback` to run once after `delay` milliseconds, like the + * global `setTimeout`. */ readonly setTimeout: (callback: TimeoutCallback, delay: number) => TTimerId - /** - * Cancels a timeout scheduled with `setTimeout`. - */ + /** Cancels a timeout scheduled with `setTimeout`. */ readonly clearTimeout: (timeoutId: TTimerId | undefined) => void /** - * Schedules `callback` to run every `delay` milliseconds, like the global `setInterval`. + * Schedules `callback` to run every `delay` milliseconds, like the global + * `setInterval`. */ readonly setInterval: (callback: TimeoutCallback, delay: number) => TTimerId - /** - * Cancels an interval scheduled with `setInterval`. - */ + /** Cancels an interval scheduled with `setInterval`. */ readonly clearInterval: (intervalId: TTimerId | undefined) => void } @@ -97,23 +96,25 @@ export class TimeoutManager implements Omit { * * This may be useful if you notice event loop performance issues with * thousands of queries. A custom TimeoutProvider could also support timer - * delays longer than the global `setTimeout` maximum delay value of about - * 24 days. + * delays longer than the global `setTimeout` maximum delay value of about 24 + * days. + * + * It is important to call `setTimeoutProvider` before creating a QueryClient + * or queries, so that the same provider is used consistently for all timers + * in the application, since different TimeoutProviders cannot cancel each + * others' timers. * - * It is important to call `setTimeoutProvider` before creating a - * QueryClient or queries, so that the same provider is used consistently - * for all timers in the application, since different TimeoutProviders - * cannot cancel each others' timers. - * @param provider - The `TimeoutProvider` to use for all timers from now on. * @example - * ```ts - * import { timeoutManager, QueryClient } from '@tanstack/query-core' - * import { CustomTimeoutProvider } from './CustomTimeoutProvider' + * ```ts + * import { timeoutManager, QueryClient } from '@tanstack/query-core' + * import { CustomTimeoutProvider } from './CustomTimeoutProvider' * - * timeoutManager.setTimeoutProvider(new CustomTimeoutProvider()) + * timeoutManager.setTimeoutProvider(new CustomTimeoutProvider()) * - * export const queryClient = new QueryClient() - * ``` + * export const queryClient = new QueryClient() + * ``` + * + * @param provider - The `TimeoutProvider` to use for all timers from now on. */ setTimeoutProvider( provider: TimeoutProvider, @@ -151,20 +152,22 @@ export class TimeoutManager implements Omit { * * It returns a timer ID, which may be a number or an object that can be * coerced to a number via `Symbol.toPrimitive`. - * @param callback - The function to call when the timeout elapses. - * @param delay - The time to wait before calling `callback`, in milliseconds. - * @returns The timer ID, to pass to {@link TimeoutManager#clearTimeout}. + * * @example - * ```ts - * import { timeoutManager } from '@tanstack/query-core' + * ```ts + * import { timeoutManager } from '@tanstack/query-core' * - * const timeoutId = timeoutManager.setTimeout( - * () => console.log('ran at:', new Date()), - * 1000, - * ) + * const timeoutId = timeoutManager.setTimeout( + * () => console.log('ran at:', new Date()), + * 1000, + * ) * - * const timeoutIdNumber: number = Number(timeoutId) - * ``` + * const timeoutIdNumber: number = Number(timeoutId) + * ``` + * + * @param callback - The function to call when the timeout elapses. + * @param delay - The time to wait before calling `callback`, in milliseconds. + * @returns The timer ID, to pass to {@link TimeoutManager#clearTimeout}. */ setTimeout(callback: TimeoutCallback, delay: number): ManagedTimerId { if (process.env.NODE_ENV !== 'production') { @@ -174,44 +177,48 @@ export class TimeoutManager implements Omit { } /** - * `clearTimeout` cancels a timeout callback scheduled with `setTimeout`, - * like the global `clearTimeout` function. It should be called with a - * timer ID returned by `setTimeout`. - * @param timeoutId - The timer ID returned by `setTimeout`, or `undefined`. + * `clearTimeout` cancels a timeout callback scheduled with `setTimeout`, like + * the global `clearTimeout` function. It should be called with a timer ID + * returned by `setTimeout`. + * * @example - * ```ts - * import { timeoutManager } from '@tanstack/query-core' + * ```ts + * import { timeoutManager } from '@tanstack/query-core' * - * const timeoutId = timeoutManager.setTimeout( - * () => console.log('ran at:', new Date()), - * 1000, - * ) + * const timeoutId = timeoutManager.setTimeout( + * () => console.log('ran at:', new Date()), + * 1000, + * ) * - * timeoutManager.clearTimeout(timeoutId) - * ``` + * timeoutManager.clearTimeout(timeoutId) + * ``` + * + * @param timeoutId - The timer ID returned by `setTimeout`, or `undefined`. */ clearTimeout(timeoutId: ManagedTimerId | undefined): void { this.#provider.clearTimeout(timeoutId) } /** - * `setInterval` schedules a callback to be called approximately every - * `delay` milliseconds, like the global `setInterval` function. + * `setInterval` schedules a callback to be called approximately every `delay` + * milliseconds, like the global `setInterval` function. * * Like `setTimeout`, it returns a timer ID, which may be a number or an * object that can be coerced to a number via `Symbol.toPrimitive`. + * + * @example + * ```ts + * import { timeoutManager } from '@tanstack/query-core' + * + * const intervalId = timeoutManager.setInterval( + * () => console.log('ran at:', new Date()), + * 1000, + * ) + * ``` + * * @param callback - The function to call on every interval. * @param delay - The time between calls, in milliseconds. * @returns The timer ID, to pass to {@link TimeoutManager#clearInterval}. - * @example - * ```ts - * import { timeoutManager } from '@tanstack/query-core' - * - * const intervalId = timeoutManager.setInterval( - * () => console.log('ran at:', new Date()), - * 1000, - * ) - * ``` */ setInterval(callback: TimeoutCallback, delay: number): ManagedTimerId { if (process.env.NODE_ENV !== 'production') { @@ -222,20 +229,22 @@ export class TimeoutManager implements Omit { /** * `clearInterval` can be used to cancel an interval, like the global - * `clearInterval` function. It should be called with an interval ID - * returned by `setInterval`. - * @param intervalId - The timer ID returned by `setInterval`, or `undefined`. + * `clearInterval` function. It should be called with an interval ID returned + * by `setInterval`. + * * @example - * ```ts - * import { timeoutManager } from '@tanstack/query-core' + * ```ts + * import { timeoutManager } from '@tanstack/query-core' * - * const intervalId = timeoutManager.setInterval( - * () => console.log('ran at:', new Date()), - * 1000, - * ) + * const intervalId = timeoutManager.setInterval( + * () => console.log('ran at:', new Date()), + * 1000, + * ) * - * timeoutManager.clearInterval(intervalId) - * ``` + * timeoutManager.clearInterval(intervalId) + * ``` + * + * @param intervalId - The timer ID returned by `setInterval`, or `undefined`. */ clearInterval(intervalId: ManagedTimerId | undefined): void { this.#provider.clearInterval(intervalId) @@ -243,7 +252,8 @@ export class TimeoutManager implements Omit { } /** - * Singleton instance of {@link TimeoutManager}, used throughout TanStack Query to schedule and cancel timers. + * Singleton instance of {@link TimeoutManager}, used throughout TanStack Query + * to schedule and cancel timers. */ export const timeoutManager = new TimeoutManager() @@ -253,6 +263,7 @@ export const timeoutManager = new TimeoutManager() * * This function is provided to make auditing the `tanstack/query-core` for * incorrect use of system `setTimeout` easier. + * * @param callback - The function to call on the next event loop tick. */ export function systemSetTimeoutZero(callback: TimeoutCallback): void { diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index fac9b158bb2..33b0cf25837 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -10,13 +10,14 @@ import type { QueryCache } from './queryCache' import type { MutationCache } from './mutationCache' /** - * Excludes `undefined` from `T`. Used where a value must be defined, such as the data type that a - * defined `initialData` resolves to. + * Excludes `undefined` from `T`. Used where a value must be defined, such as + * the data type that a defined `initialData` resolves to. */ export type NonUndefinedGuard = T extends undefined ? never : T /** - * Like `Omit`, but applied to each member of a union separately, so each member keeps its own keys. + * Like `Omit`, but applied to each member of a union separately, so each member + * keeps its own keys. */ export type DistributiveOmit< TObject, @@ -24,8 +25,9 @@ export type DistributiveOmit< > = TObject extends any ? Omit : never /** - * Like `Omit`, but by default (`'strictly'`) `TKey` must be a key of `TObject`, so omitting a key - * that doesn't exist is a type error. Pass `'safely'` to allow other keys too. + * Like `Omit`, but by default (`'strictly'`) `TKey` must be a key of `TObject`, + * so omitting a key that doesn't exist is a type error. Pass `'safely'` to + * allow other keys too. */ export type OmitKeyof< TObject, @@ -40,8 +42,9 @@ export type OmitKeyof< > = Omit /** - * Replaces the types of the properties of `TTargetA` that also exist in `TTargetB` with their types - * in `TTargetB`. Properties that only exist in `TTargetB` are not added. + * Replaces the types of the properties of `TTargetA` that also exist in + * `TTargetB` with their types in `TTargetB`. Properties that only exist in + * `TTargetB` are not added. */ export type Override = { [AKey in keyof TTargetA]: AKey extends keyof TTargetB @@ -50,23 +53,26 @@ export type Override = { } /** - * The interface to augment via declaration merging to override Query's default types repository-wide. - * Each field it declares replaces the default of the matching type: `defaultError` for {@link DefaultError}, - * `queryKey` for {@link QueryKey}, `mutationKey` for {@link MutationKey}, `queryMeta` for {@link QueryMeta} and - * `mutationMeta` for {@link MutationMeta}. Leave a field out to keep that type's default. - * Augment the module you install — `@tanstack/react-query`, `@tanstack/vue-query`, - * `@tanstack/solid-query`, `@tanstack/svelte-query`, `@tanstack/preact-query`, - * `@tanstack/angular-query-experimental` or `@tanstack/lit-query`. Augmenting `@tanstack/query-core` - * works too and covers every adapter at once. + * The interface to augment via declaration merging to override Query's default + * types repository-wide. Each field it declares replaces the default of the + * matching type: `defaultError` for {@link DefaultError}, `queryKey` for + * {@link QueryKey}, `mutationKey` for {@link MutationKey}, `queryMeta` for + * {@link QueryMeta} and `mutationMeta` for {@link MutationMeta}. Leave a field + * out to keep that type's default. Augment the module you install — + * `@tanstack/react-query`, `@tanstack/vue-query`, `@tanstack/solid-query`, + * `@tanstack/svelte-query`, `@tanstack/preact-query`, + * `@tanstack/angular-query-experimental` or `@tanstack/lit-query`. Augmenting + * `@tanstack/query-core` works too and covers every adapter at once. + * * @example - * ```ts - * // Use the module you installed — here, the React adapter. - * declare module '@tanstack/react-query' { - * interface Register { - * defaultError: AxiosError + * ```ts + * // Use the module you installed — here, the React adapter. + * declare module '@tanstack/react-query' { + * interface Register { + * defaultError: AxiosError + * } * } - * } - * ``` + * ``` */ export interface Register { // defaultError: Error @@ -77,8 +83,9 @@ export interface Register { } /** - * The error type used wherever an error is not given an explicit type parameter. - * Defaults to `Error`; declare `defaultError` on {@link Register} to change it everywhere at once. + * The error type used wherever an error is not given an explicit type + * parameter. Defaults to `Error`; declare `defaultError` on {@link Register} to + * change it everywhere at once. */ export type DefaultError = Register extends { defaultError: infer TError @@ -87,8 +94,9 @@ export type DefaultError = Register extends { : Error /** - * The type of a query key — the serializable array that identifies a query in the cache. - * Defaults to `ReadonlyArray`; declare `queryKey` on {@link Register} to narrow it repository-wide. + * The type of a query key — the serializable array that identifies a query in + * the cache. Defaults to `ReadonlyArray`; declare `queryKey` on + * {@link Register} to narrow it repository-wide. */ export type QueryKey = Register extends { queryKey: infer TQueryKey @@ -102,37 +110,36 @@ export type QueryKey = Register extends { export const dataTagSymbol = Symbol() /** - * The type of the `dataTagSymbol` key, under which a {@link DataTag} stores its data type. + * The type of the `dataTagSymbol` key, under which a {@link DataTag} stores its + * data type. */ export type dataTagSymbol = typeof dataTagSymbol export const dataTagErrorSymbol = Symbol() /** - * The type of the `dataTagErrorSymbol` key, under which a {@link DataTag} stores its error type. + * The type of the `dataTagErrorSymbol` key, under which a {@link DataTag} stores + * its error type. */ export type dataTagErrorSymbol = typeof dataTagErrorSymbol export const unsetMarker = Symbol() /** - * The type of `unsetMarker`, the default error type of a {@link DataTag}. It marks that no error - * type was tagged. + * The type of `unsetMarker`, the default error type of a {@link DataTag}. It + * marks that no error type was tagged. */ export type UnsetMarker = typeof unsetMarker /** - * Matches any type that has been tagged with {@link DataTag}, whatever its data and error types. + * Matches any type that has been tagged with {@link DataTag}, whatever its data + * and error types. */ export type AnyDataTag = { - /** - * The data type the key was tagged with. - */ + /** The data type the key was tagged with. */ [dataTagSymbol]: any - /** - * The error type the key was tagged with. - */ + /** The error type the key was tagged with. */ [dataTagErrorSymbol]: any } /** - * Tags `TType` (usually a query key) with a data type and an optional error type, so that APIs that - * receive it, like `queryClient.getQueryData`, can infer them. A type that is already tagged is - * returned as is. + * Tags `TType` (usually a query key) with a data type and an optional error + * type, so that APIs that receive it, like `queryClient.getQueryData`, can + * infer them. A type that is already tagged is returned as is. */ export type DataTag< TType, @@ -146,23 +153,21 @@ export type DataTag< } /** - * An object whose `queryKey` is tagged with {@link DataTag}, like the options returned by - * `queryOptions`. + * An object whose `queryKey` is tagged with {@link DataTag}, like the options + * returned by `queryOptions`. */ export type QueryKeyWithDataTag< TQueryKey extends QueryKey = QueryKey, TQueryFnData = unknown, TError = DefaultError, > = { - /** - * The query key, tagged with the query's data and error types. - */ + /** The query key, tagged with the query's data and error types. */ queryKey: DataTag } /** - * The data type tagged on a query key by {@link DataTag}, or `TQueryFnData` if the key is not - * tagged. + * The data type tagged on a query key by {@link DataTag}, or `TQueryFnData` if + * the key is not tagged. */ export type InferDataFromTag = TTaggedQueryKey extends DataTag @@ -170,8 +175,8 @@ export type InferDataFromTag = : TQueryFnData /** - * The error type tagged on a query key by {@link DataTag}, or `TError` if the key is not tagged or - * was tagged without an error type. + * The error type tagged on a query key by {@link DataTag}, or `TError` if the + * key is not tagged or was tagged without an error type. */ export type InferErrorFromTag = TTaggedQueryKey extends DataTag @@ -228,9 +233,9 @@ export type QueryPersister< ) => T | Promise /** - * The object passed to `queryFn`: the `QueryClient`, the `queryKey`, an `AbortSignal` that aborts - * when the query is cancelled, the query's `meta`, and for infinite queries the `pageParam` of the - * page being fetched. + * The object passed to `queryFn`: the `QueryClient`, the `queryKey`, an + * `AbortSignal` that aborts when the query is cancelled, the query's `meta`, + * and for infinite queries the `pageParam` of the page being fetched. */ export type QueryFunctionContext< TQueryKey extends QueryKey = QueryKey, @@ -278,9 +283,9 @@ export type PlaceholderDataFunction< ) => TQueryData | undefined /** - * The `placeholderData` function of a query in `useQueries` and its counterparts. Unlike - * {@link PlaceholderDataFunction}, it receives no previous data or query, because the number of - * queries can differ between renders. + * The `placeholderData` function of a query in `useQueries` and its + * counterparts. Unlike {@link PlaceholderDataFunction}, it receives no previous + * data or query, because the number of queries can differ between renders. */ export type QueriesPlaceholderDataFunction = ( previousData: undefined, @@ -309,23 +314,22 @@ export type GetNextPageParamFunction = ( ) => TPageParam | undefined | null /** - * The data shape of an infinite query: every page fetched so far, plus the page param each one was fetched with. - * `pages` and `pageParams` are index-aligned — `pageParams[i]` is the param that produced `pages[i]`. + * The data shape of an infinite query: every page fetched so far, plus the page + * param each one was fetched with. `pages` and `pageParams` are index-aligned — + * `pageParams[i]` is the param that produced `pages[i]`. */ export interface InfiniteData { - /** - * The data of every page fetched so far, in order. - */ + /** The data of every page fetched so far, in order. */ pages: Array - /** - * The page param each page was fetched with, aligned by index with `pages`. - */ + /** The page param each page was fetched with, aligned by index with `pages`. */ pageParams: Array } /** - * The type of the `meta` object that can be attached to a query and read back from `queryFn`, callbacks and - * cache-level handlers. Defaults to `Record`; declare `queryMeta` on {@link Register} to narrow it. + * The type of the `meta` object that can be attached to a query and read back + * from `queryFn`, callbacks and cache-level handlers. Defaults to + * `Record`; declare `queryMeta` on {@link Register} to narrow + * it. */ export type QueryMeta = Register extends { queryMeta: infer TQueryMeta @@ -346,8 +350,9 @@ export type NotifyOnChangeProps = | (() => Array | 'all' | undefined) /** - * The options of a query itself — its `queryKey`, `queryFn`, retries, `gcTime`, `initialData`, - * `meta`, and so on — shared by observers and the `QueryClient` methods that fetch queries. + * The options of a query itself — its `queryKey`, `queryFn`, retries, `gcTime`, + * `initialData`, `meta`, and so on — shared by observers and the `QueryClient` + * methods that fetch queries. */ export interface QueryOptions< TQueryFnData = unknown, @@ -357,93 +362,105 @@ export interface QueryOptions< TPageParam = never, > { /** - * If `false`, failed queries will not retry by default. - * If `true`, failed queries will retry infinitely. - * If set to an integer number, e.g. 3, failed queries will retry until the failed query count meets that number. - * If set to a function `(failureCount, error) => boolean` failed queries will retry until the function returns false. + * If `false`, failed queries will not retry by default. If `true`, failed + * queries will retry infinitely. If set to an integer number, e.g. 3, failed + * queries will retry until the failed query count meets that number. If set + * to a function `(failureCount, error) => boolean` failed queries will retry + * until the function returns false. * * Defaults to `3` on the client and `0` on the server. */ retry?: RetryValue /** - * This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the - * next attempt in milliseconds. + * This function receives a `retryAttempt` integer and the actual Error and + * returns the delay to apply before the next attempt in milliseconds. * - * A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000)` applies exponential - * backoff. + * A function like `attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : + * 1000, 30 * 1000)` applies exponential backoff. * * A function like `attempt => attempt * 1000` applies linear backoff. * - * Defaults to a function that applies exponential backoff, capped at 30 seconds. + * Defaults to a function that applies exponential backoff, capped at 30 + * seconds. */ retryDelay?: RetryDelayValue /** - * Controls whether a query is allowed to run based on the current network connectivity. + * Controls whether a query is allowed to run based on the current network + * connectivity. + * * @defaultValue 'online' * @see [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. */ networkMode?: NetworkMode /** * The time in milliseconds that unused/inactive cache data remains in memory. - * When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. - * When different garbage collection times are specified, the longest one will be used. - * Setting it to `Infinity` will disable garbage collection. + * When a query's cache becomes unused or inactive, that cache data will be + * garbage collected after this duration. When different garbage collection + * times are specified, the longest one will be used. Setting it to `Infinity` + * will disable garbage collection. * * Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. * - * Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s 32-bit signed integer delay — see - * `timeoutManager.setTimeoutProvider` for a workaround. + * Note: the maximum allowed time is about 24 days, imposed by `setTimeout`'s + * 32-bit signed integer delay — see `timeoutManager.setTimeoutProvider` for a + * workaround. */ gcTime?: number /** - * The function that the query will use to request data. - * Required, unless a default query function has been set via `queryClient.setQueryDefaults` or - * `queryClient.setDefaultOptions`. - * Receives a {@link QueryFunctionContext}. - * Must return a promise that will either resolve data or throw an error. The data cannot be `undefined`. + * The function that the query will use to request data. Required, unless a + * default query function has been set via `queryClient.setQueryDefaults` or + * `queryClient.setDefaultOptions`. Receives a {@link QueryFunctionContext}. + * Must return a promise that will either resolve data or throw an error. The + * data cannot be `undefined`. */ queryFn?: QueryFunction | SkipToken /** - * This option can be used to persist the result of a query to an external storage, bypassing the need to actually - * call the `queryFn`. Useful for persisting a query's data across e.g. server/client boundaries. + * This option can be used to persist the result of a query to an external + * storage, bypassing the need to actually call the `queryFn`. Useful for + * persisting a query's data across e.g. server/client boundaries. */ persister?: QueryPersister, TPageParam> /** - * The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the default hashing function otherwise). Used - * as the actual cache key internally. + * The hashed form of `queryKey`, computed with `queryKeyHashFn` (or the + * default hashing function otherwise). Used as the actual cache key + * internally. */ queryHash?: string /** * The query key to use for this query. * - * The query key will be hashed into a stable hash. See [Query Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) + * The query key will be hashed into a stable hash. See [Query + * Keys](https://tanstack.com/query/latest/docs/framework/react/guides/query-keys) * for more information. * - * The query will automatically update when this key changes (as long as `enabled` is not set to `false`). + * The query will automatically update when this key changes (as long as + * `enabled` is not set to `false`). */ queryKey?: TQueryKey - /** - * If specified, this function is used to hash the `queryKey` to a string. - */ + /** If specified, this function is used to hash the `queryKey` to a string. */ queryKeyHashFn?: QueryKeyHashFunction /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). - * If set to a function, the function will be called **once** during the shared/root query initialization, and be - * expected to synchronously return the initial data. - * Initial data is considered stale by default unless a `staleTime` has been set. - * `initialData` **is persisted** to the cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData?: TData | InitialDataFunction /** - * If set, this value will be used as the time (in milliseconds) of when the `initialData` itself was last updated. + * If set, this value will be used as the time (in milliseconds) of when the + * `initialData` itself was last updated. */ initialDataUpdatedAt?: number | (() => number | undefined) /** @internal */ behavior?: QueryBehavior /** * Set this to `false` to disable structural sharing between query results. - * Set this to a function which accepts the old and new data and returns resolved data of the same type to implement custom structural sharing logic. + * Set this to a function which accepts the old and new data and returns + * resolved data of the same type to implement custom structural sharing + * logic. + * * @defaultValue true */ structuralSharing?: @@ -454,46 +471,45 @@ export interface QueryOptions< /** @internal */ _type?: 'infinite' /** - * Additional payload to be stored on each query. - * Use this property to pass information that can be used in other places. + * Additional payload to be stored on each query. Use this property to pass + * information that can be used in other places. */ meta?: QueryMeta - /** - * Maximum number of pages to store in the data of an infinite query. - */ + /** Maximum number of pages to store in the data of an infinite query. */ maxPages?: number } -/** - * Holds the `initialPageParam` option that every infinite query requires. - */ +/** Holds the `initialPageParam` option that every infinite query requires. */ export interface InitialPageParam { /** - * The page param to start from when an infinite query has no pages yet. - * It is passed to `queryFn` as `pageParam` for the first page; every page after that gets the - * value returned by `getNextPageParam` or `getPreviousPageParam`. - * It only applies while the query has no pages: once a first page exists, refetching starts from - * that page's own param instead. + * The page param to start from when an infinite query has no pages yet. It is + * passed to `queryFn` as `pageParam` for the first page; every page after + * that gets the value returned by `getNextPageParam` or + * `getPreviousPageParam`. It only applies while the query has no pages: once + * a first page exists, refetching starts from that page's own param instead. */ initialPageParam: TPageParam } /** - * The page param options of an infinite query: `initialPageParam`, and the `getNextPageParam` and - * `getPreviousPageParam` functions that compute the params of the pages around it. + * The page param options of an infinite query: `initialPageParam`, and the + * `getNextPageParam` and `getPreviousPageParam` functions that compute the + * params of the pages around it. */ export interface InfiniteQueryPageParamsOptions< TQueryFnData = unknown, TPageParam = unknown, > extends InitialPageParam { /** - * This function can be set to automatically get the previous cursor for infinite queries. - * The result will also be used to determine the value of `hasPreviousPage`. + * This function can be set to automatically get the previous cursor for + * infinite queries. The result will also be used to determine the value of + * `hasPreviousPage`. */ getPreviousPageParam?: GetPreviousPageParamFunction /** - * This function can be set to automatically get the next cursor for infinite queries. - * The result will also be used to determine the value of `hasNextPage`. + * This function can be set to automatically get the next cursor for infinite + * queries. The result will also be used to determine the value of + * `hasNextPage`. */ getNextPageParam: GetNextPageParamFunction } @@ -512,9 +528,10 @@ export type ThrowOnError< ) => boolean) /** - * The options of a `QueryObserver`, and of the hooks built on it like `useQuery`: the - * {@link QueryOptions} of the query, plus options that control the observer, such as `enabled`, - * `staleTime`, `refetchInterval`, `select`, and `placeholderData`. + * The options of a `QueryObserver`, and of the hooks built on it like + * `useQuery`: the {@link QueryOptions} of the query, plus options that control + * the observer, such as `enabled`, `staleTime`, `refetchInterval`, `select`, + * and `placeholderData`. */ export interface QueryObserverOptions< TQueryFnData = unknown, @@ -528,23 +545,28 @@ export interface QueryObserverOptions< 'queryKey' > { /** - * Set this to `false` or a function that returns `false` to disable automatic refetching when the query mounts or changes query keys. - * To refetch the query, use the `refetch` method returned from the `useQuery` instance. + * Set this to `false` or a function that returns `false` to disable automatic + * refetching when the query mounts or changes query keys. To refetch the + * query, use the `refetch` method returned from the `useQuery` instance. * Accepts a boolean or function that returns a boolean. + * * @defaultValue true */ enabled?: QueryBooleanOption /** - * The time in milliseconds after data is considered stale. - * If set to `Infinity`, the data will never be considered stale. - * If set to `'static'`, the data will never be considered stale. - * If set to a function, the function will be executed with the query to compute a `staleTime`. + * The time in milliseconds after data is considered stale. If set to + * `Infinity`, the data will never be considered stale. If set to `'static'`, + * the data will never be considered stale. If set to a function, the function + * will be executed with the query to compute a `staleTime`. + * * @defaultValue 0 */ staleTime?: StaleTimeFunction /** - * If set to a number, the query will continuously refetch at this frequency in milliseconds. - * If set to a function, the function will be executed with the latest data and query to compute a frequency + * If set to a number, the query will continuously refetch at this frequency + * in milliseconds. If set to a function, the function will be executed with + * the latest data and query to compute a frequency + * * @defaultValue false */ refetchInterval?: @@ -554,15 +576,19 @@ export interface QueryObserverOptions< query: Query, ) => number | false | undefined) /** - * If set to `true`, the query will continue to refetch while their tab/window is in the background. + * If set to `true`, the query will continue to refetch while their tab/window + * is in the background. + * * @defaultValue false */ refetchIntervalInBackground?: boolean /** - * If set to `true`, the query will refetch on window focus if the data is stale. - * If set to `false`, the query will not refetch on window focus. - * If set to `'always'`, the query will always refetch on window focus (except when `staleTime: 'static'` is used). - * If set to a function, the function will be executed with the latest data and query to compute the value. + * If set to `true`, the query will refetch on window focus if the data is + * stale. If set to `false`, the query will not refetch on window focus. If + * set to `'always'`, the query will always refetch on window focus (except + * when `staleTime: 'static'` is used). If set to a function, the function + * will be executed with the latest data and query to compute the value. + * * @defaultValue true */ refetchOnWindowFocus?: @@ -573,9 +599,10 @@ export interface QueryObserverOptions< ) => boolean | 'always') /** * If set to `true`, the query will refetch on reconnect if the data is stale. - * If set to `false`, the query will not refetch on reconnect. - * If set to `'always'`, the query will always refetch on reconnect (except when `staleTime: 'static'` is used). - * If set to a function, the function will be executed with the latest data and query to compute the value. + * If set to `false`, the query will not refetch on reconnect. If set to + * `'always'`, the query will always refetch on reconnect (except when + * `staleTime: 'static'` is used). If set to a function, the function will be + * executed with the latest data and query to compute the value. * * Defaults to `true` unless `networkMode` is `'always'`. */ @@ -586,10 +613,13 @@ export interface QueryObserverOptions< query: Query, ) => boolean | 'always') /** - * If set to `true`, the query will refetch on mount if the data is stale. - * If set to `false`, will disable additional instances of a query to trigger background refetch. - * If set to `'always'`, the query will always refetch on mount (except when `staleTime: 'static'` is used). - * If set to a function, the function will be executed with the latest data and query to compute the value + * If set to `true`, the query will refetch on mount if the data is stale. If + * set to `false`, will disable additional instances of a query to trigger + * background refetch. If set to `'always'`, the query will always refetch on + * mount (except when `staleTime: 'static'` is used). If set to a function, + * the function will be executed with the latest data and query to compute the + * value + * * @defaultValue true */ refetchOnMount?: @@ -599,44 +629,57 @@ export interface QueryObserverOptions< query: Query, ) => boolean | 'always') /** - * If set to `false`, the query will not be retried on mount if it contains an error. - * If set to a function, the function will be executed with the query to compute the value. + * If set to `false`, the query will not be retried on mount if it contains an + * error. If set to a function, the function will be executed with the query + * to compute the value. + * * @defaultValue true */ retryOnMount?: QueryBooleanOption /** - * If set, the component will only re-render if any of the listed properties change. - * When set to `['data', 'error']`, the component will only re-render when the `data` or `error` properties change. - * When set to `'all'`, the component will re-render whenever a query is updated. - * When set to a function, the function will be executed to compute the list of properties. + * If set, the component will only re-render if any of the listed properties + * change. When set to `['data', 'error']`, the component will only re-render + * when the `data` or `error` properties change. When set to `'all'`, the + * component will re-render whenever a query is updated. When set to a + * function, the function will be executed to compute the list of properties. * - * Defaults to `undefined`, in which case property access is tracked automatically, and the - * component only re-renders when one of the tracked properties changes. + * Defaults to `undefined`, in which case property access is tracked + * automatically, and the component only re-renders when one of the tracked + * properties changes. */ notifyOnChangeProps?: NotifyOnChangeProps /** - * Whether errors should be thrown instead of setting the `error` property. - * If set to `true` or `suspense` is `true`, all errors will be thrown to the error boundary. - * If set to `false` and `suspense` is `false`, errors are returned as state. - * If set to a function, it will be passed the error and the query, and it should return a boolean indicating whether to show the error in an error boundary (`true`) or return the error as state (`false`). + * Whether errors should be thrown instead of setting the `error` property. If + * set to `true` or `suspense` is `true`, all errors will be thrown to the + * error boundary. If set to `false` and `suspense` is `false`, errors are + * returned as state. If set to a function, it will be passed the error and + * the query, and it should return a boolean indicating whether to show the + * error in an error boundary (`true`) or return the error as state + * (`false`). + * * @defaultValue false */ throwOnError?: ThrowOnError /** - * This option can be used to transform or select a part of the data returned by the query function. It affects - * the returned `data` value, but does not affect what gets stored in the query cache. - * The `select` function will only run if `data` changed, or if the reference to the `select` function itself - * changes. To optimize, memoize the function so its reference stays stable across calls. + * This option can be used to transform or select a part of the data returned + * by the query function. It affects the returned `data` value, but does not + * affect what gets stored in the query cache. The `select` function will only + * run if `data` changed, or if the reference to the `select` function itself + * changes. To optimize, memoize the function so its reference stays stable + * across calls. */ select?: (data: TQueryData) => TData /** - * If set to `true`, the query will suspend when `status === 'pending'` - * and throw errors when `status === 'error'`. + * If set to `true`, the query will suspend when `status === 'pending'` and + * throw errors when `status === 'error'`. + * * @defaultValue false */ suspense?: boolean /** - * 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. + * 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 @@ -651,16 +694,15 @@ export interface QueryObserverOptions< _optimisticResults?: 'optimistic' | 'isRestoring' } -/** - * Makes the `TKey` properties of `TTarget` required and non-nullable. - */ +/** Makes the `TKey` properties of `TTarget` required and non-nullable. */ export type WithRequired = TTarget & { [_ in TKey]: {} } /** - * The {@link QueryObserverOptions} after `QueryClient#defaultQueryOptions` has applied the - * defaults, so `throwOnError`, `refetchOnReconnect`, and `queryHash` are always set. + * The {@link QueryObserverOptions} after `QueryClient#defaultQueryOptions` has + * applied the defaults, so `throwOnError`, `refetchOnReconnect`, and + * `queryHash` are always set. */ export type DefaultedQueryObserverOptions< TQueryFnData = unknown, @@ -674,8 +716,8 @@ export type DefaultedQueryObserverOptions< > /** - * The options of an `InfiniteQueryObserver`: {@link QueryObserverOptions} whose query data is - * {@link InfiniteData}, plus the page param options. + * The options of an `InfiniteQueryObserver`: {@link QueryObserverOptions} whose + * query data is {@link InfiniteData}, plus the page param options. */ export interface InfiniteQueryObserverOptions< TQueryFnData = unknown, @@ -696,8 +738,9 @@ export interface InfiniteQueryObserverOptions< InfiniteQueryPageParamsOptions {} /** - * The {@link InfiniteQueryObserverOptions} after `QueryClient#defaultQueryOptions` has applied the - * defaults, so `throwOnError`, `refetchOnReconnect`, and `queryHash` are always set. + * The {@link InfiniteQueryObserverOptions} after + * `QueryClient#defaultQueryOptions` has applied the defaults, so + * `throwOnError`, `refetchOnReconnect`, and `queryHash` are always set. */ export type DefaultedInfiniteQueryObserverOptions< TQueryFnData = unknown, @@ -717,9 +760,10 @@ export type DefaultedInfiniteQueryObserverOptions< > /** - * The options of `queryClient.query`: the {@link QueryOptions} of the query, plus a `staleTime` - * that decides whether cached data is returned instead of fetching, and a `select` that only - * transforms the value the call resolves with. + * The options of `queryClient.query`: the {@link QueryOptions} of the query, + * plus a `staleTime` that decides whether cached data is returned instead of + * fetching, and a `select` that only transforms the value the call resolves + * with. */ export interface QueryExecuteOptions< TQueryFnData = unknown, @@ -733,17 +777,19 @@ export interface QueryExecuteOptions< 'queryKey' > { /** - * Not allowed here, since `initialPageParam` only applies to infinite queries. + * Not allowed here, since `initialPageParam` only applies to infinite + * queries. */ initialPageParam?: never /** - * This option can be used to transform or select a part of the data returned by the query function. It affects - * the value this call resolves with, but does not affect what gets stored in the query cache. + * This option can be used to transform or select a part of the data returned + * by the query function. It affects the value this call resolves with, but + * does not affect what gets stored in the query cache. */ select?: (data: TQueryData) => TData /** - * The time in milliseconds after data is considered stale. - * If the data is fresh it will be returned from the cache. + * The time in milliseconds after data is considered stale. If the data is + * fresh it will be returned from the cache. */ staleTime?: StaleTimeFunction } @@ -760,12 +806,13 @@ export interface FetchQueryOptions< 'queryKey' > { /** - * Not allowed here, since `initialPageParam` only applies to infinite queries. + * Not allowed here, since `initialPageParam` only applies to infinite + * queries. */ initialPageParam?: never /** - * The time in milliseconds after data is considered stale. - * If the data is fresh it will be returned from the cache. + * The time in milliseconds after data is considered stale. If the data is + * fresh it will be returned from the cache. */ staleTime?: StaleTimeFunction } @@ -785,7 +832,8 @@ export interface EnsureQueryDataOptions< TPageParam > { /** - * If `true`, stale cached data is returned and also refetched in the background. + * If `true`, stale cached data is returned and also refetched in the + * background. */ revalidateIfStale?: boolean } @@ -815,9 +863,9 @@ type InfiniteQueryPages = } /** - * The options of `queryClient.infiniteQuery`: like {@link QueryExecuteOptions}, with the - * `initialPageParam`, and optionally `pages` together with `getNextPageParam` to fetch that many - * pages at once. + * The options of `queryClient.infiniteQuery`: like {@link QueryExecuteOptions}, + * with the `initialPageParam`, and optionally `pages` together with + * `getNextPageParam` to fetch that many pages at once. */ export type InfiniteQueryExecuteOptions< TQueryFnData = unknown, @@ -860,90 +908,105 @@ export type FetchInfiniteQueryOptions< InfiniteQueryPages /** - * Options shared by the `QueryClient` and observer methods that refetch queries, controlling - * whether a failed refetch makes the returned promise reject. + * Options shared by the `QueryClient` and observer methods that refetch + * queries, controlling whether a failed refetch makes the returned promise + * reject. */ export interface ResultOptions { /** - * If set to `true`, the method throws if any of the underlying query refetch tasks fail. - * If set to `false`, failed refetches are swallowed and not surfaced to the caller. + * If set to `true`, the method throws if any of the underlying query refetch + * tasks fail. If set to `false`, failed refetches are swallowed and not + * surfaced to the caller. + * * @defaultValue false */ throwOnError?: boolean } /** - * Options of the methods that refetch queries, like `refetch` and `queryClient.refetchQueries`. + * Options of the methods that refetch queries, like `refetch` and + * `queryClient.refetchQueries`. */ export interface RefetchOptions extends ResultOptions { /** - * If set to `true`, a currently running request will be cancelled before a new request is made + * If set to `true`, a currently running request will be cancelled before a + * new request is made + * + * If set to `false`, no refetch will be made if there is already a request + * running. * - * If set to `false`, no refetch will be made if there is already a request running. * @defaultValue true */ cancelRefetch?: boolean } /** - * The filters of `queryClient.invalidateQueries`: the {@link QueryFilters} that select the queries - * to invalidate, plus `refetchType` to choose which of them are refetched. + * The filters of `queryClient.invalidateQueries`: the {@link QueryFilters} that + * select the queries to invalidate, plus `refetchType` to choose which of them + * are refetched. */ export interface InvalidateQueryFilters< TQueryKey extends QueryKey = QueryKey, > extends QueryFilters { /** - * Controls which of the matched (now-invalidated) queries are refetched in the background. + * Controls which of the matched (now-invalidated) queries are refetched in + * the background. * * - `'active'`: only queries with at least one active observer are refetched. * - `'inactive'`: only queries with no active observer are refetched. * - `'all'`: every matched query is refetched, active or not. - * - `'none'`: no query is refetched; matched queries are only marked as invalidated. + * - `'none'`: no query is refetched; matched queries are only marked as + * invalidated. + * * @defaultValue 'active' */ refetchType?: QueryTypeFilter | 'none' } /** - * The filters of `queryClient.refetchQueries`, which select the queries to refetch. + * The filters of `queryClient.refetchQueries`, which select the queries to + * refetch. */ export interface RefetchQueryFilters< TQueryKey extends QueryKey = QueryKey, > extends QueryFilters {} /** - * Options of `queryClient.invalidateQueries`, applied to the refetch that follows the invalidation. + * Options of `queryClient.invalidateQueries`, applied to the refetch that + * follows the invalidation. */ export interface InvalidateOptions extends RefetchOptions {} /** - * Options of `queryClient.resetQueries`, applied to the refetch of the active queries after the - * reset. + * Options of `queryClient.resetQueries`, applied to the refetch of the active + * queries after the reset. */ export interface ResetOptions extends RefetchOptions {} -/** - * Options of `fetchNextPage` on an infinite query result. - */ +/** Options of `fetchNextPage` on an infinite query result. */ export interface FetchNextPageOptions extends ResultOptions { /** - * If set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` every time, - * whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. + * If set to `true`, calling `fetchNextPage` repeatedly will invoke `queryFn` + * every time, whether the previous invocation has resolved or not. Also, the + * result from previous invocations will be ignored. + * + * If set to `false`, calling `fetchNextPage` repeatedly won't have any effect + * until the first invocation has resolved. * - * If set to `false`, calling `fetchNextPage` repeatedly won't have any effect until the first invocation has resolved. * @defaultValue true */ cancelRefetch?: boolean } -/** - * Options of `fetchPreviousPage` on an infinite query result. - */ +/** Options of `fetchPreviousPage` on an infinite query result. */ export interface FetchPreviousPageOptions extends ResultOptions { /** - * If set to `true`, calling `fetchPreviousPage` repeatedly will invoke `queryFn` every time, - * whether the previous invocation has resolved or not. Also, the result from previous invocations will be ignored. + * If set to `true`, calling `fetchPreviousPage` repeatedly will invoke + * `queryFn` every time, whether the previous invocation has resolved or not. + * Also, the result from previous invocations will be ignored. + * + * If set to `false`, calling `fetchPreviousPage` repeatedly won't have any + * effect until the first invocation has resolved. * - * If set to `false`, calling `fetchPreviousPage` repeatedly won't have any effect until the first invocation has resolved. * @defaultValue true */ cancelRefetch?: boolean @@ -955,76 +1018,81 @@ export type QueryStatus = 'pending' | 'error' | 'success' export type FetchStatus = 'fetching' | 'paused' | 'idle' /** - * The properties shared by every state of a query result, like `data`, `error`, `status`, the - * `is*` flags, and `refetch`. Each `QueryObserver*Result` narrows them for one state. + * The properties shared by every state of a query result, like `data`, `error`, + * `status`, the `is*` flags, and `refetch`. Each `QueryObserver*Result` narrows + * them for one state. */ export interface QueryObserverBaseResult< TData = unknown, TError = DefaultError, > { - /** - * The last successfully resolved data for the query. - */ + /** The last successfully resolved data for the query. */ data: TData | undefined /** - * The timestamp for when the query most recently returned the `status` as `"success"`. + * The timestamp for when the query most recently returned the `status` as + * `"success"`. */ dataUpdatedAt: number /** * The error object for the query, if an error was thrown. + * * - Defaults to `null`. */ error: TError | null /** - * The timestamp for when the query most recently returned the `status` as `"error"`. + * The timestamp for when the query most recently returned the `status` as + * `"error"`. */ errorUpdatedAt: number /** * The failure count for the query. + * * - Incremented every time the query fails. * - Reset to `0` when the query succeeds. */ failureCount: number /** * The failure reason for the query retry. + * * - Reset to `null` when the query succeeds. */ failureReason: TError | null - /** - * The sum of all errors. - */ + /** The sum of all errors. */ errorUpdateCount: number /** * A derived boolean from the `status` variable, provided for convenience. + * * - `true` if the query attempt resulted in an error. */ isError: boolean - /** - * Will be `true` if the query has been fetched. - */ + /** Will be `true` if the query has been fetched. */ isFetched: boolean /** * Will be `true` if the query has been fetched after the component mounted. + * * - This property can be used to not show any previously cached data. */ isFetchedAfterMount: boolean /** - * A derived boolean from the `fetchStatus` variable, provided for convenience. - * - `true` whenever the `queryFn` is executing, which includes initial `pending` as well as background refetch. + * A derived boolean from the `fetchStatus` variable, provided for + * convenience. + * + * - `true` whenever the `queryFn` is executing, which includes initial + * `pending` as well as background refetch. */ isFetching: boolean /** * Is `true` whenever the first fetch for a query is in-flight. + * * - Is the same as `isFetching && isPending`. */ isLoading: boolean /** - * Will be `pending` if there's no cached data and no query attempt was finished yet. + * Will be `pending` if there's no cached data and no query attempt was + * finished yet. */ isPending: boolean - /** - * Will be `true` if the query failed while fetching for the first time. - */ + /** Will be `true` if the query failed while fetching for the first time. */ isLoadingError: boolean /** * @deprecated `isInitialLoading` is being deprecated in favor of `isLoading` @@ -1032,357 +1100,251 @@ export interface QueryObserverBaseResult< */ isInitialLoading: boolean /** - * A derived boolean from the `fetchStatus` variable, provided for convenience. + * A derived boolean from the `fetchStatus` variable, provided for + * convenience. + * * - The query wanted to fetch, but has been `paused`. */ isPaused: boolean - /** - * Will be `true` if the data shown is the placeholder data. - */ + /** Will be `true` if the data shown is the placeholder data. */ isPlaceholderData: boolean - /** - * Will be `true` if the query failed while refetching. - */ + /** Will be `true` if the query failed while refetching. */ isRefetchError: boolean /** - * Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending`. + * Is `true` whenever a background refetch is in-flight, which _does not_ + * include initial `pending`. + * * - Is the same as `isFetching && !isPending`. */ isRefetching: boolean /** - * Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`. + * Will be `true` if the data in the cache is invalidated or if the data is + * older than the given `staleTime`. */ isStale: boolean /** * A derived boolean from the `status` variable, provided for convenience. - * - `true` if the query has received a response with no errors and is ready to display its data. + * + * - `true` if the query has received a response with no errors and is ready to + * display its data. */ isSuccess: boolean - /** - * `true` if this observer is enabled, `false` otherwise. - */ + /** `true` if this observer is enabled, `false` otherwise. */ isEnabled: boolean - /** - * A function to manually refetch the query. - */ + /** A function to manually refetch the query. */ refetch: ( options?: RefetchOptions, ) => Promise> /** * The status of the query. + * * - Will be: + * * - `pending` if there's no cached data and no query attempt was finished yet. * - `error` if the query attempt resulted in an error. - * - `success` if the query has received a response with no errors and is ready to display its data. + * - `success` if the query has received a response with no errors and is ready + * to display its data. */ status: QueryStatus /** * The fetch status of the query. - * - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch. + * + * - `fetching`: Is `true` whenever the queryFn is executing, which includes + * initial `pending` as well as background refetch. * - `paused`: The query wanted to fetch, but has been `paused`. * - `idle`: The query is not fetching. - * - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. + * - See [Network + * Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) + * for more information. */ fetchStatus: FetchStatus } -/** - * A query result in the `pending` state: the query has no data yet. - */ +/** A query result in the `pending` state: the query has no data yet. */ export interface QueryObserverPendingResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * `undefined`, since the query has no data yet. - */ + /** `undefined`, since the query has no data yet. */ data: undefined - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `true`, since there's no cached data and no query attempt has finished yet. - */ + /** `true`, since there's no cached data and no query attempt has finished yet. */ isPending: true - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'pending'`, since there's no cached data and no query attempt has finished yet. + * `'pending'`, since there's no cached data and no query attempt has finished + * yet. */ status: 'pending' } /** - * A query result in the `pending` state while the first fetch is in flight, so `isLoading` is - * `true`. + * A query result in the `pending` state while the first fetch is in flight, so + * `isLoading` is `true`. */ export interface QueryObserverLoadingResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * `undefined`, since the query has no data yet. - */ + /** `undefined`, since the query has no data yet. */ data: undefined - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `true`, since there's no cached data and no query attempt has finished yet. - */ + /** `true`, since there's no cached data and no query attempt has finished yet. */ isPending: true - /** - * `true`, since the first fetch is in flight. - */ + /** `true`, since the first fetch is in flight. */ isLoading: true - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'pending'`, since there's no cached data and no query attempt has finished yet. + * `'pending'`, since there's no cached data and no query attempt has finished + * yet. */ status: 'pending' } /** - * A query result in the `error` state when the first fetch failed, so there is no data. + * A query result in the `error` state when the first fetch failed, so there is + * no data. */ export interface QueryObserverLoadingErrorResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * `undefined`, since the first fetch failed before any data was cached. - */ + /** `undefined`, since the first fetch failed before any data was cached. */ data: undefined - /** - * The error the first fetch failed with. - */ + /** The error the first fetch failed with. */ error: TError - /** - * `true`, since the query is in the `error` state. - */ + /** `true`, since the query is in the `error` state. */ isError: true - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `true`, since the query failed while fetching for the first time. - */ + /** `true`, since the query failed while fetching for the first time. */ isLoadingError: true - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false - /** - * `'error'`, since the query attempt resulted in an error. - */ + /** `'error'`, since the query attempt resulted in an error. */ status: 'error' } /** - * A query result in the `error` state when a refetch failed, so the data from before is kept. + * A query result in the `error` state when a refetch failed, so the data from + * before is kept. */ export interface QueryObserverRefetchErrorResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * The data from before the failed refetch, which is kept. - */ + /** The data from before the failed refetch, which is kept. */ data: TData - /** - * The error the refetch failed with. - */ + /** The error the refetch failed with. */ error: TError - /** - * `true`, since the query is in the `error` state. - */ + /** `true`, since the query is in the `error` state. */ isError: true - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `true`, since the query failed while refetching. - */ + /** `true`, since the query failed while refetching. */ isRefetchError: true - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false - /** - * `'error'`, since the query attempt resulted in an error. - */ + /** `'error'`, since the query attempt resulted in an error. */ status: 'error' } -/** - * A query result in the `success` state with data from the cache. - */ +/** A query result in the `success` state with data from the cache. */ export interface QueryObserverSuccessResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * The last successfully resolved data for the query. - */ + /** The last successfully resolved data for the query. */ data: TData - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `true`, since the query is in the `success` state. - */ + /** `true`, since the query is in the `success` state. */ isSuccess: true - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'success'`, since the query has received a response with no errors and is ready to display its - * data. + * `'success'`, since the query has received a response with no errors and is + * ready to display its data. */ status: 'success' } /** - * A query result in the `success` state that shows `placeholderData` while the query has no data - * yet. + * A query result in the `success` state that shows `placeholderData` while the + * query has no data yet. */ export interface QueryObserverPlaceholderResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * The `placeholderData` shown while the query has no data yet. - */ + /** The `placeholderData` shown while the query has no data yet. */ data: TData - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `true`, since the query is in the `success` state. - */ + /** `true`, since the query is in the `success` state. */ isSuccess: true - /** - * `true`, since the data shown is the `placeholderData`. - */ + /** `true`, since the data shown is the `placeholderData`. */ isPlaceholderData: true /** - * `'success'`, since the query has received a response with no errors and is ready to display its - * data. + * `'success'`, since the query has received a response with no errors and is + * ready to display its data. */ status: 'success' } -/** - * A query result that always has `data`: the success and refetch error states. - */ +/** A query result that always has `data`: the success and refetch error states. */ export type DefinedQueryObserverResult< TData = unknown, TError = DefaultError, @@ -1391,8 +1353,9 @@ export type DefinedQueryObserverResult< | QueryObserverSuccessResult /** - * The result of a `QueryObserver`, and of the hooks built on it like `useQuery`. Narrow it by - * `status` or the `is*` flags to get the type of each state. + * The result of a `QueryObserver`, and of the hooks built on it like + * `useQuery`. Narrow it by `status` or the `is*` flags to get the type of each + * state. */ export type QueryObserverResult = | DefinedQueryObserverResult @@ -1403,388 +1366,248 @@ export type QueryObserverResult = /** * The properties shared by every state of an infinite query result: those of - * {@link QueryObserverBaseResult}, plus `fetchNextPage`, `fetchPreviousPage`, and the flags about - * them, like `hasNextPage` and `isFetchingNextPage`. + * {@link QueryObserverBaseResult}, plus `fetchNextPage`, `fetchPreviousPage`, + * and the flags about them, like `hasNextPage` and `isFetchingNextPage`. */ export interface InfiniteQueryObserverBaseResult< TData = unknown, TError = DefaultError, > extends QueryObserverBaseResult { - /** - * This function allows you to fetch the next "page" of results. - */ + /** This function allows you to fetch the next "page" of results. */ fetchNextPage: ( options?: FetchNextPageOptions, ) => Promise> - /** - * This function allows you to fetch the previous "page" of results. - */ + /** This function allows you to fetch the previous "page" of results. */ fetchPreviousPage: ( options?: FetchPreviousPageOptions, ) => Promise> /** - * Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option). + * Will be `true` if there is a next page to be fetched (known via the + * `getNextPageParam` option). */ hasNextPage: boolean /** - * Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option). + * Will be `true` if there is a previous page to be fetched (known via the + * `getPreviousPageParam` option). */ hasPreviousPage: boolean - /** - * Will be `true` if the query failed while fetching the next page. - */ + /** Will be `true` if the query failed while fetching the next page. */ isFetchNextPageError: boolean - /** - * Will be `true` while fetching the next page with `fetchNextPage`. - */ + /** Will be `true` while fetching the next page with `fetchNextPage`. */ isFetchingNextPage: boolean - /** - * Will be `true` if the query failed while fetching the previous page. - */ + /** Will be `true` if the query failed while fetching the previous page. */ isFetchPreviousPageError: boolean - /** - * Will be `true` while fetching the previous page with `fetchPreviousPage`. - */ + /** Will be `true` while fetching the previous page with `fetchPreviousPage`. */ isFetchingPreviousPage: boolean } -/** - * An infinite query result in the `pending` state: the query has no data yet. - */ +/** An infinite query result in the `pending` state: the query has no data yet. */ export interface InfiniteQueryObserverPendingResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * `undefined`, since the query has no data yet. - */ + /** `undefined`, since the query has no data yet. */ data: undefined - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `true`, since there's no cached data and no query attempt has finished yet. - */ + /** `true`, since there's no cached data and no query attempt has finished yet. */ isPending: true - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since fetching the next page didn't fail. - */ + /** `false`, since fetching the next page didn't fail. */ isFetchNextPageError: false - /** - * `false`, since fetching the previous page didn't fail. - */ + /** `false`, since fetching the previous page didn't fail. */ isFetchPreviousPageError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'pending'`, since there's no cached data and no query attempt has finished yet. + * `'pending'`, since there's no cached data and no query attempt has finished + * yet. */ status: 'pending' } /** - * An infinite query result in the `pending` state while the first fetch is in flight, so - * `isLoading` is `true`. + * An infinite query result in the `pending` state while the first fetch is in + * flight, so `isLoading` is `true`. */ export interface InfiniteQueryObserverLoadingResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * `undefined`, since the query has no data yet. - */ + /** `undefined`, since the query has no data yet. */ data: undefined - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `true`, since there's no cached data and no query attempt has finished yet. - */ + /** `true`, since there's no cached data and no query attempt has finished yet. */ isPending: true - /** - * `true`, since the first fetch is in flight. - */ + /** `true`, since the first fetch is in flight. */ isLoading: true - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since fetching the next page didn't fail. - */ + /** `false`, since fetching the next page didn't fail. */ isFetchNextPageError: false - /** - * `false`, since fetching the previous page didn't fail. - */ + /** `false`, since fetching the previous page didn't fail. */ isFetchPreviousPageError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'pending'`, since there's no cached data and no query attempt has finished yet. + * `'pending'`, since there's no cached data and no query attempt has finished + * yet. */ status: 'pending' } /** - * An infinite query result in the `error` state when the first fetch failed, so there is no data. + * An infinite query result in the `error` state when the first fetch failed, so + * there is no data. */ export interface InfiniteQueryObserverLoadingErrorResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * `undefined`, since the first fetch failed before any data was cached. - */ + /** `undefined`, since the first fetch failed before any data was cached. */ data: undefined - /** - * The error the first fetch failed with. - */ + /** The error the first fetch failed with. */ error: TError - /** - * `true`, since the query is in the `error` state. - */ + /** `true`, since the query is in the `error` state. */ isError: true - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `true`, since the query failed while fetching for the first time. - */ + /** `true`, since the query failed while fetching for the first time. */ isLoadingError: true - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since fetching the next page didn't fail. - */ + /** `false`, since fetching the next page didn't fail. */ isFetchNextPageError: false - /** - * `false`, since fetching the previous page didn't fail. - */ + /** `false`, since fetching the previous page didn't fail. */ isFetchPreviousPageError: false - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false - /** - * `'error'`, since the query attempt resulted in an error. - */ + /** `'error'`, since the query attempt resulted in an error. */ status: 'error' } /** - * An infinite query result in the `error` state when a refetch failed, so the data from before is - * kept. + * An infinite query result in the `error` state when a refetch failed, so the + * data from before is kept. */ export interface InfiniteQueryObserverRefetchErrorResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * The data from before the failed refetch, which is kept. - */ + /** The data from before the failed refetch, which is kept. */ data: TData - /** - * The error the refetch failed with. - */ + /** The error the refetch failed with. */ error: TError - /** - * `true`, since the query is in the `error` state. - */ + /** `true`, since the query is in the `error` state. */ isError: true - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `true`, since the query failed while refetching. - */ + /** `true`, since the query failed while refetching. */ isRefetchError: true - /** - * `false`, since the query isn't in the `success` state. - */ + /** `false`, since the query isn't in the `success` state. */ isSuccess: false - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false - /** - * `'error'`, since the query attempt resulted in an error. - */ + /** `'error'`, since the query attempt resulted in an error. */ status: 'error' } -/** - * An infinite query result in the `success` state with data from the cache. - */ +/** An infinite query result in the `success` state with data from the cache. */ export interface InfiniteQueryObserverSuccessResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * The last successfully resolved data for the query. - */ + /** The last successfully resolved data for the query. */ data: TData - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `false`, since fetching the next page didn't fail. - */ + /** `false`, since fetching the next page didn't fail. */ isFetchNextPageError: false - /** - * `false`, since fetching the previous page didn't fail. - */ + /** `false`, since fetching the previous page didn't fail. */ isFetchPreviousPageError: false - /** - * `true`, since the query is in the `success` state. - */ + /** `true`, since the query is in the `success` state. */ isSuccess: true - /** - * `false`, since the data shown isn't the `placeholderData`. - */ + /** `false`, since the data shown isn't the `placeholderData`. */ isPlaceholderData: false /** - * `'success'`, since the query has received a response with no errors and is ready to display its - * data. + * `'success'`, since the query has received a response with no errors and is + * ready to display its data. */ status: 'success' } /** - * An infinite query result in the `success` state that shows `placeholderData` while the query has - * no data yet. + * An infinite query result in the `success` state that shows `placeholderData` + * while the query has no data yet. */ export interface InfiniteQueryObserverPlaceholderResult< TData = unknown, TError = DefaultError, > extends InfiniteQueryObserverBaseResult { - /** - * The `placeholderData` shown while the query has no data yet. - */ + /** The `placeholderData` shown while the query has no data yet. */ data: TData - /** - * `false`, since the query isn't in the `error` state. - */ + /** `false`, since the query isn't in the `error` state. */ isError: false - /** - * `null`, since the query isn't in the `error` state. - */ + /** `null`, since the query isn't in the `error` state. */ error: null - /** - * `false`, since the query has data or a query attempt has finished. - */ + /** `false`, since the query has data or a query attempt has finished. */ isPending: false - /** - * `false`, since the first fetch isn't in flight. - */ + /** `false`, since the first fetch isn't in flight. */ isLoading: false - /** - * `false`, since the query didn't fail while fetching for the first time. - */ + /** `false`, since the query didn't fail while fetching for the first time. */ isLoadingError: false - /** - * `false`, since the query didn't fail while refetching. - */ + /** `false`, since the query didn't fail while refetching. */ isRefetchError: false - /** - * `true`, since the query is in the `success` state. - */ + /** `true`, since the query is in the `success` state. */ isSuccess: true - /** - * `true`, since the data shown is the `placeholderData`. - */ + /** `true`, since the data shown is the `placeholderData`. */ isPlaceholderData: true - /** - * `false`, since fetching the next page didn't fail. - */ + /** `false`, since fetching the next page didn't fail. */ isFetchNextPageError: false - /** - * `false`, since fetching the previous page didn't fail. - */ + /** `false`, since fetching the previous page didn't fail. */ isFetchPreviousPageError: false /** - * `'success'`, since the query has received a response with no errors and is ready to display its - * data. + * `'success'`, since the query has received a response with no errors and is + * ready to display its data. */ status: 'success' } /** - * An infinite query result that always has `data`: the success and refetch error states. + * An infinite query result that always has `data`: the success and refetch + * error states. */ export type DefinedInfiniteQueryObserverResult< TData = unknown, @@ -1794,8 +1617,9 @@ export type DefinedInfiniteQueryObserverResult< | InfiniteQueryObserverSuccessResult /** - * The result of an `InfiniteQueryObserver`, and of the hooks built on it like `useInfiniteQuery`. - * Narrow it by `status` or the `is*` flags to get the type of each state. + * The result of an `InfiniteQueryObserver`, and of the hooks built on it like + * `useInfiniteQuery`. Narrow it by `status` or the `is*` flags to get the type + * of each state. */ export type InfiniteQueryObserverResult< TData = unknown, @@ -1808,8 +1632,9 @@ export type InfiniteQueryObserverResult< | InfiniteQueryObserverPlaceholderResult /** - * The type of a mutation key — the serializable array used to identify and filter mutations. - * Defaults to `ReadonlyArray`; declare `mutationKey` on {@link Register} to narrow it repository-wide. + * The type of a mutation key — the serializable array used to identify and + * filter mutations. Defaults to `ReadonlyArray`; declare `mutationKey` + * on {@link Register} to narrow it repository-wide. */ export type MutationKey = Register extends { mutationKey: infer TMutationKey @@ -1826,19 +1651,20 @@ export type MutationStatus = 'idle' | 'pending' | 'success' | 'error' /** * Groups mutations so they run one after another instead of in parallel. - * Mutations that share the same `id` form a queue: while one is running, the others wait in `isPaused: true` - * state and resume automatically when their turn comes. Mutations with no scope always run in parallel. + * Mutations that share the same `id` form a queue: while one is running, the + * others wait in `isPaused: true` state and resume automatically when their + * turn comes. Mutations with no scope always run in parallel. */ export type MutationScope = { - /** - * The scope's identifier. Mutations with the same `id` run one after another. - */ + /** The scope's identifier. Mutations with the same `id` run one after another. */ id: string } /** - * The type of the `meta` object that can be attached to a mutation and read back from `mutationFn`, callbacks and - * cache-level handlers. Defaults to `Record`; declare `mutationMeta` on {@link Register} to narrow it. + * The type of the `meta` object that can be attached to a mutation and read + * back from `mutationFn`, callbacks and cache-level handlers. Defaults to + * `Record`; declare `mutationMeta` on {@link Register} to + * narrow it. */ export type MutationMeta = Register extends { mutationMeta: infer TMutationMeta @@ -1849,21 +1675,15 @@ export type MutationMeta = Register extends { : Record /** - * The object passed to `mutationFn` and the mutation callbacks: the `QueryClient`, the mutation's - * `meta`, and its `mutationKey`. + * The object passed to `mutationFn` and the mutation callbacks: the + * `QueryClient`, the mutation's `meta`, and its `mutationKey`. */ export type MutationFunctionContext = { - /** - * The `QueryClient` the mutation runs in. - */ + /** The `QueryClient` the mutation runs in. */ client: QueryClient - /** - * The `meta` of the mutation options. - */ + /** The `meta` of the mutation options. */ meta: MutationMeta | undefined - /** - * The `mutationKey` of the mutation options, if set. - */ + /** The `mutationKey` of the mutation options, if set. */ mutationKey?: MutationKey } @@ -1874,8 +1694,8 @@ export type MutationFunction = ( ) => Promise /** - * The options of a mutation: its `mutationFn`, `mutationKey`, callbacks, retries, `scope`, and so - * on. + * The options of a mutation: its `mutationFn`, `mutationKey`, callbacks, + * retries, `scope`, and so on. */ export interface MutationOptions< TData = unknown, @@ -1885,33 +1705,35 @@ export interface MutationOptions< > { /** * The function that performs the asynchronous task this mutation runs. - * Required, unless a default mutation function has been set for the matching `mutationKey` via - * `queryClient.setMutationDefaults`. - * Receives the `variables` passed to `mutate`, and a {@link MutationFunctionContext} holding the - * `QueryClient`, the `mutationKey` and `meta`. - * Must return a promise that resolves the mutation's data. + * Required, unless a default mutation function has been set for the matching + * `mutationKey` via `queryClient.setMutationDefaults`. Receives the + * `variables` passed to `mutate`, and a {@link MutationFunctionContext} + * holding the `QueryClient`, the `mutationKey` and `meta`. Must return a + * promise that resolves the mutation's data. */ mutationFn?: MutationFunction /** - * The key to use for this mutation. Optional, but required to inherit defaults registered with - * `queryClient.setMutationDefaults`, and to match this mutation with `useMutationState` or - * `queryClient.isMutating`. + * The key to use for this mutation. Optional, but required to inherit + * defaults registered with `queryClient.setMutationDefaults`, and to match + * this mutation with `useMutationState` or `queryClient.isMutating`. */ mutationKey?: MutationKey /** - * This function fires before the mutation function runs, and receives the same variables. - * Useful for optimistic updates applied in the hope that the mutation succeeds. - * The value it returns is passed to `onSuccess`, `onError` and `onSettled` as `onMutateResult`, - * which is where an optimistic update is usually rolled back. - * If a promise is returned, it is awaited before the mutation function runs. + * This function fires before the mutation function runs, and receives the + * same variables. Useful for optimistic updates applied in the hope that the + * mutation succeeds. The value it returns is passed to `onSuccess`, `onError` + * and `onSettled` as `onMutateResult`, which is where an optimistic update is + * usually rolled back. If a promise is returned, it is awaited before the + * mutation function runs. */ onMutate?: ( variables: TVariables, context: MutationFunctionContext, ) => Promise | TOnMutateResult /** - * This function fires when the mutation succeeds, and is passed the mutation's result. - * If a promise is returned, it is awaited before `onSettled` runs. + * This function fires when the mutation succeeds, and is passed the + * mutation's result. If a promise is returned, it is awaited before + * `onSettled` runs. */ onSuccess?: ( data: TData, @@ -1920,8 +1742,9 @@ export interface MutationOptions< context: MutationFunctionContext, ) => Promise | unknown /** - * This function fires when the mutation encounters an error, and is passed the error. - * If a promise is returned, it is awaited before `onSettled` runs. + * This function fires when the mutation encounters an error, and is passed + * the error. If a promise is returned, it is awaited before `onSettled` + * runs. */ onError?: ( error: TError, @@ -1930,9 +1753,9 @@ export interface MutationOptions< context: MutationFunctionContext, ) => Promise | unknown /** - * This function fires when the mutation either succeeds or errors, and is passed either the data - * or the error. - * If a promise is returned, it is awaited before the mutation settles. + * This function fires when the mutation either succeeds or errors, and is + * passed either the data or the error. If a promise is returned, it is + * awaited before the mutation settles. */ onSettled?: ( data: TData | undefined, @@ -1942,29 +1765,34 @@ export interface MutationOptions< context: MutationFunctionContext, ) => Promise | unknown /** - * If `false`, failed mutations will not retry by default. - * If `true`, failed mutations will retry infinitely. - * If set to an integer number, e.g. 3, failed mutations will retry until the failed mutation count meets that number. - * If set to a function `(failureCount, error) => boolean` failed mutations will retry until the function returns false. + * If `false`, failed mutations will not retry by default. If `true`, failed + * mutations will retry infinitely. If set to an integer number, e.g. 3, + * failed mutations will retry until the failed mutation count meets that + * number. If set to a function `(failureCount, error) => boolean` failed + * mutations will retry until the function returns false. + * * @defaultValue 0 */ retry?: RetryValue /** - * This function receives a `retryAttempt` integer and the actual Error and returns the delay to apply before the - * next attempt in milliseconds. + * This function receives a `retryAttempt` integer and the actual Error and + * returns the delay to apply before the next attempt in milliseconds. * - * Defaults to a function that applies exponential backoff, capped at 30 seconds. + * Defaults to a function that applies exponential backoff, capped at 30 + * seconds. */ retryDelay?: RetryDelayValue /** - * Controls whether a mutation is allowed to run based on the current network connectivity. + * Controls whether a mutation is allowed to run based on the current network + * connectivity. + * * @defaultValue 'online' * @see [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information. */ networkMode?: NetworkMode /** - * The time in milliseconds that an unused/inactive mutation remains in memory before it is - * garbage collected. + * The time in milliseconds that an unused/inactive mutation remains in memory + * before it is garbage collected. * * Defaults to `5 * 60 * 1000` (5 minutes), or `Infinity` during SSR. */ @@ -1972,22 +1800,22 @@ export interface MutationOptions< /** @internal */ _defaulted?: boolean /** - * Additional payload to be stored on the mutation cache entry. - * Use it to pass information that can be read wherever the `mutation` is available, such as the - * `onError` and `onSuccess` callbacks of the `MutationCache`. + * Additional payload to be stored on the mutation cache entry. Use it to pass + * information that can be read wherever the `mutation` is available, such as + * the `onError` and `onSuccess` callbacks of the `MutationCache`. */ meta?: MutationMeta /** * Controls whether this mutation runs alongside others or waits its turn. - * Mutations sharing the same `scope.id` run serially, in the order they were started. - * Without a scope, a mutation runs as soon as it is triggered. + * Mutations sharing the same `scope.id` run serially, in the order they were + * started. Without a scope, a mutation runs as soon as it is triggered. */ scope?: MutationScope } /** - * The options of a `MutationObserver`, and of the hooks built on it like `useMutation`: the - * {@link MutationOptions}, plus `throwOnError`. + * The options of a `MutationObserver`, and of the hooks built on it like + * `useMutation`: the {@link MutationOptions}, plus `throwOnError`. */ export interface MutationObserverOptions< TData = unknown, @@ -1996,18 +1824,20 @@ export interface MutationObserverOptions< TOnMutateResult = unknown, > extends MutationOptions { /** - * Whether errors should be thrown instead of setting the `error` property. - * If set to `true`, all errors will be thrown to the nearest error boundary. - * If set to a function, it will be passed the error and should return a boolean indicating whether to throw the - * error (`true`) or return it as state (`false`). + * Whether errors should be thrown instead of setting the `error` property. If + * set to `true`, all errors will be thrown to the nearest error boundary. If + * set to a function, it will be passed the error and should return a boolean + * indicating whether to throw the error (`true`) or return it as state + * (`false`). + * * @defaultValue false */ throwOnError?: boolean | ((error: TError) => boolean) } /** - * The callbacks that can be passed to `mutate` for a single call. They run after the callbacks of - * the mutation options. + * The callbacks that can be passed to `mutate` for a single call. They run + * after the callbacks of the mutation options. */ export interface MutateOptions< TData = unknown, @@ -2016,7 +1846,8 @@ export interface MutateOptions< TOnMutateResult = unknown, > { /** - * Called when the mutation of this call succeeds, after the `onSuccess` of the mutation options. + * Called when the mutation of this call succeeds, after the `onSuccess` of + * the mutation options. */ onSuccess?: ( data: TData, @@ -2025,7 +1856,8 @@ export interface MutateOptions< context: MutationFunctionContext, ) => void /** - * Called when the mutation of this call fails, after the `onError` of the mutation options. + * Called when the mutation of this call fails, after the `onError` of the + * mutation options. */ onError?: ( error: TError, @@ -2034,8 +1866,8 @@ export interface MutateOptions< context: MutationFunctionContext, ) => void /** - * Called when the mutation of this call succeeds or fails, after the `onSettled` of the mutation - * options. + * Called when the mutation of this call succeeds or fails, after the + * `onSettled` of the mutation options. */ onSettled?: ( data: TData | undefined, @@ -2047,8 +1879,8 @@ export interface MutateOptions< } /** - * The parameters of {@link MutateFunction}: `variables`, optional when `TVariables` accepts - * `undefined`, and the {@link MutateOptions} for that call. + * The parameters of {@link MutateFunction}: `variables`, optional when + * `TVariables` accepts `undefined`, and the {@link MutateOptions} for that call. */ export type MutateFunctionRest< TData = unknown, @@ -2066,8 +1898,8 @@ export type MutateFunctionRest< ] /** - * The `mutate` function of a `MutationObserver`: runs the mutation with the given variables and - * resolves with its data. + * The `mutate` function of a `MutationObserver`: runs the mutation with the + * given variables and resolves with its data. */ export type MutateFunction< TData = unknown, @@ -2079,8 +1911,8 @@ export type MutateFunction< ) => Promise /** - * The properties shared by every state of a mutation result, like `data`, `error`, `variables`, - * `status`, the `is*` flags, `mutate`, and `reset`. + * The properties shared by every state of a mutation result, like `data`, + * `error`, `variables`, `status`, the `is*` flags, `mutate`, and `reset`. */ export interface MutationObserverBaseResult< TData = unknown, @@ -2088,42 +1920,45 @@ export interface MutationObserverBaseResult< TVariables = void, TOnMutateResult = unknown, > extends MutationState { - /** - * The last successfully resolved data for the mutation. - */ + /** The last successfully resolved data for the mutation. */ data: TData | undefined - /** - * The variables object passed to the `mutationFn`. - */ + /** The variables object passed to the `mutationFn`. */ variables: TVariables | undefined /** * The error object for the mutation, if an error was encountered. + * * - Defaults to `null`. */ error: TError | null /** * A boolean variable derived from `status`. + * * - `true` if the last mutation attempt resulted in an error. */ isError: boolean /** * A boolean variable derived from `status`. + * * - `true` if the mutation is in its initial state prior to executing. */ isIdle: boolean /** * A boolean variable derived from `status`. + * * - `true` if the mutation is currently executing. */ isPending: boolean /** * A boolean variable derived from `status`. + * * - `true` if the last mutation attempt was successful. */ isSuccess: boolean /** * The status of the mutation. + * * - Will be: + * * - `idle` initial status prior to the mutation function executing. * - `pending` if the mutation is currently executing. * - `error` if the last mutation attempt resulted in an error. @@ -2131,24 +1966,34 @@ export interface MutationObserverBaseResult< */ status: MutationStatus /** - * The mutation function you can call with variables to trigger the mutation and optionally hooks on additional callback options. - * @param variables - The variables object to pass to the `mutationFn`. - * @param options.onSuccess - This function will fire when the mutation is successful and will be passed the mutation's result. - * @param options.onError - This function will fire if the mutation encounters an error and will be passed the error. - * @param options.onSettled - This function will fire when the mutation is either successfully fetched or encounters an error and be passed either the data or error. + * The mutation function you can call with variables to trigger the mutation + * and optionally hooks on additional callback options. + * * @remarks - * - If you make multiple requests, `onSuccess` will fire only after the latest call you've made. - * - All the callback functions (`onSuccess`, `onError`, `onSettled`) are void functions, and the returned value will be ignored. + * - If you make multiple requests, `onSuccess` will fire only after the + * latest call you've made. + * - All the callback functions (`onSuccess`, `onError`, `onSettled`) are void + * functions, and the returned value will be ignored. + * @param variables - The variables object to pass to the `mutationFn`. + * @param options.onSuccess - This function will fire when the mutation is + * successful and will be passed the mutation's result. + * @param options.onError - This function will fire if the mutation encounters + * an error and will be passed the error. + * @param options.onSettled - This function will fire when the mutation is + * either successfully fetched or encounters an error and be passed either + * the data or error. */ mutate: MutateFunction /** - * A function to clean the mutation internal state (i.e., it resets the mutation to its initial state). + * A function to clean the mutation internal state (i.e., it resets the + * mutation to its initial state). */ reset: () => void } /** - * A mutation result in the `idle` state: the mutation hasn't run yet, or was reset. + * A mutation result in the `idle` state: the mutation hasn't run yet, or was + * reset. */ export interface MutationObserverIdleResult< TData = unknown, @@ -2161,43 +2006,25 @@ export interface MutationObserverIdleResult< TVariables, TOnMutateResult > { - /** - * `undefined`, since the mutation hasn't run. - */ + /** `undefined`, since the mutation hasn't run. */ data: undefined - /** - * `undefined`, since the mutation hasn't run. - */ + /** `undefined`, since the mutation hasn't run. */ variables: undefined - /** - * `null`, since the mutation hasn't failed. - */ + /** `null`, since the mutation hasn't failed. */ error: null - /** - * `false`, since the mutation hasn't failed. - */ + /** `false`, since the mutation hasn't failed. */ isError: false - /** - * `true`, since the mutation hasn't run yet or was reset. - */ + /** `true`, since the mutation hasn't run yet or was reset. */ isIdle: true - /** - * `false`, since the mutation isn't running. - */ + /** `false`, since the mutation isn't running. */ isPending: false - /** - * `false`, since the mutation hasn't succeeded. - */ + /** `false`, since the mutation hasn't succeeded. */ isSuccess: false - /** - * `'idle'`, since the mutation hasn't run yet or was reset. - */ + /** `'idle'`, since the mutation hasn't run yet or was reset. */ status: 'idle' } -/** - * A mutation result in the `pending` state while the mutation runs. - */ +/** A mutation result in the `pending` state while the mutation runs. */ export interface MutationObserverLoadingResult< TData = unknown, TError = DefaultError, @@ -2209,43 +2036,25 @@ export interface MutationObserverLoadingResult< TVariables, TOnMutateResult > { - /** - * `undefined`, since the mutation hasn't succeeded. - */ + /** `undefined`, since the mutation hasn't succeeded. */ data: undefined - /** - * The variables passed to `mutate` for this mutation. - */ + /** The variables passed to `mutate` for this mutation. */ variables: TVariables - /** - * `null`, since the mutation hasn't failed. - */ + /** `null`, since the mutation hasn't failed. */ error: null - /** - * `false`, since the mutation hasn't failed. - */ + /** `false`, since the mutation hasn't failed. */ isError: false - /** - * `false`, since the mutation has run. - */ + /** `false`, since the mutation has run. */ isIdle: false - /** - * `true`, since the mutation is running. - */ + /** `true`, since the mutation is running. */ isPending: true - /** - * `false`, since the mutation hasn't succeeded. - */ + /** `false`, since the mutation hasn't succeeded. */ isSuccess: false - /** - * `'pending'`, since the mutation is running. - */ + /** `'pending'`, since the mutation is running. */ status: 'pending' } -/** - * A mutation result in the `error` state after the mutation failed. - */ +/** A mutation result in the `error` state after the mutation failed. */ export interface MutationObserverErrorResult< TData = unknown, TError = DefaultError, @@ -2257,43 +2066,25 @@ export interface MutationObserverErrorResult< TVariables, TOnMutateResult > { - /** - * `undefined`, since the mutation hasn't succeeded. - */ + /** `undefined`, since the mutation hasn't succeeded. */ data: undefined - /** - * The error the mutation failed with. - */ + /** The error the mutation failed with. */ error: TError - /** - * The variables passed to `mutate` for this mutation. - */ + /** The variables passed to `mutate` for this mutation. */ variables: TVariables - /** - * `true`, since the mutation failed. - */ + /** `true`, since the mutation failed. */ isError: true - /** - * `false`, since the mutation has run. - */ + /** `false`, since the mutation has run. */ isIdle: false - /** - * `false`, since the mutation isn't running. - */ + /** `false`, since the mutation isn't running. */ isPending: false - /** - * `false`, since the mutation hasn't succeeded. - */ + /** `false`, since the mutation hasn't succeeded. */ isSuccess: false - /** - * `'error'`, since the mutation failed. - */ + /** `'error'`, since the mutation failed. */ status: 'error' } -/** - * A mutation result in the `success` state after the mutation succeeded. - */ +/** A mutation result in the `success` state after the mutation succeeded. */ export interface MutationObserverSuccessResult< TData = unknown, TError = DefaultError, @@ -2305,43 +2096,28 @@ export interface MutationObserverSuccessResult< TVariables, TOnMutateResult > { - /** - * The data the mutation resolved with. - */ + /** The data the mutation resolved with. */ data: TData - /** - * `null`, since the mutation hasn't failed. - */ + /** `null`, since the mutation hasn't failed. */ error: null - /** - * The variables passed to `mutate` for this mutation. - */ + /** The variables passed to `mutate` for this mutation. */ variables: TVariables - /** - * `false`, since the mutation hasn't failed. - */ + /** `false`, since the mutation hasn't failed. */ isError: false - /** - * `false`, since the mutation has run. - */ + /** `false`, since the mutation has run. */ isIdle: false - /** - * `false`, since the mutation isn't running. - */ + /** `false`, since the mutation isn't running. */ isPending: false - /** - * `true`, since the mutation succeeded. - */ + /** `true`, since the mutation succeeded. */ isSuccess: true - /** - * `'success'`, since the mutation succeeded. - */ + /** `'success'`, since the mutation succeeded. */ status: 'success' } /** - * The result of a `MutationObserver`, and of the hooks built on it like `useMutation`. Narrow it by - * `status` or the `is*` flags to get the type of each state. + * The result of a `MutationObserver`, and of the hooks built on it like + * `useMutation`. Narrow it by `status` or the `is*` flags to get the type of + * each state. */ export type MutationObserverResult< TData = unknown, @@ -2355,15 +2131,18 @@ export type MutationObserverResult< | MutationObserverSuccessResult /** - * The options of `new QueryClient()`: the `queryCache` and `mutationCache` to use, and the - * `defaultOptions` for its queries and mutations. + * The options of `new QueryClient()`: the `queryCache` and `mutationCache` to + * use, and the `defaultOptions` for its queries and mutations. */ export interface QueryClientConfig { - /** The query cache this client is connected to. A new `QueryCache` is created if not provided. */ + /** + * The query cache this client is connected to. A new `QueryCache` is created + * if not provided. + */ queryCache?: QueryCache /** - * The mutation cache this client is connected to. A new `MutationCache` is created if not - * provided. + * The mutation cache this client is connected to. A new `MutationCache` is + * created if not provided. */ mutationCache?: MutationCache /** Default options for all queries and mutations created through this client. */ @@ -2371,8 +2150,8 @@ export interface QueryClientConfig { } /** - * The default options of a `QueryClient`, applied to every query (`queries`), mutation - * (`mutations`), `hydrate`, and `dehydrate` call unless overridden. + * The default options of a `QueryClient`, applied to every query (`queries`), + * mutation (`mutations`), `hydrate`, and `dehydrate` call unless overridden. */ export interface DefaultOptions { /** Default options applied to every query, unless overridden per-query. */ @@ -2382,38 +2161,46 @@ export interface DefaultOptions { > /** Default options applied to every mutation, unless overridden per-mutation. */ mutations?: MutationObserverOptions - /** Default options used when hydrating queries and mutations; see {@link HydrateOptions}. */ + /** + * Default options used when hydrating queries and mutations; see + * {@link HydrateOptions}. + */ hydrate?: HydrateOptions['defaultOptions'] - /** Default options used when dehydrating the client's caches; see {@link DehydrateOptions}. */ + /** + * Default options used when dehydrating the client's caches; see + * {@link DehydrateOptions}. + */ dehydrate?: DehydrateOptions } /** - * Options for cancelling an in-flight fetch, e.g. via `query.cancel()`. - * They are carried on the {@link CancelledError} that the cancelled fetch rejects with. + * Options for cancelling an in-flight fetch, e.g. via `query.cancel()`. They + * are carried on the {@link CancelledError} that the cancelled fetch rejects + * with. */ export interface CancelOptions { /** - * If `true`, the query goes back to the state it had before the fetch started, instead of getting - * the cancellation error. + * If `true`, the query goes back to the state it had before the fetch + * started, instead of getting the cancellation error. */ revert?: boolean /** - * If `true`, the cancellation error isn't surfaced, e.g. because another fetch replaces the - * cancelled one. + * If `true`, the cancellation error isn't surfaced, e.g. because another + * fetch replaces the cancelled one. */ silent?: boolean } /** - * Options for writing data into the cache, e.g. via `queryClient.setQueryData()`. - * `updatedAt` overrides the timestamp the data is recorded with, which is what staleness is measured from; - * omit it to use the current time. + * Options for writing data into the cache, e.g. via + * `queryClient.setQueryData()`. `updatedAt` overrides the timestamp the data is + * recorded with, which is what staleness is measured from; omit it to use the + * current time. */ export interface SetDataOptions { /** - * The timestamp to record the data with, instead of the current time. Staleness is measured from - * it. + * The timestamp to record the data with, instead of the current time. + * Staleness is measured from it. */ updatedAt?: number } @@ -2429,11 +2216,10 @@ export type NotifyEventType = | 'observerOptionsUpdated' /** - * The base shape of the events that the query and mutation caches send to their listeners. + * The base shape of the events that the query and mutation caches send to their + * listeners. */ export interface NotifyEvent { - /** - * The kind of event, e.g. `'added'`, `'removed'`, or `'updated'`. - */ + /** The kind of event, e.g. `'added'`, `'removed'`, or `'updated'`. */ type: NotifyEventType } diff --git a/packages/query-core/src/utils.ts b/packages/query-core/src/utils.ts index e17cbcc3175..a6bb2180219 100644 --- a/packages/query-core/src/utils.ts +++ b/packages/query-core/src/utils.ts @@ -25,40 +25,33 @@ type TuplePrefixes> = T extends readonly [] : TuplePrefixes> | T /** - * Filters used to select queries, for example in `queryClient.getQueriesData` or `queryClient.invalidateQueries`. - * All provided filters must match; filters that are left unspecified are ignored. + * Filters used to select queries, for example in `queryClient.getQueriesData` + * or `queryClient.invalidateQueries`. All provided filters must match; filters + * that are left unspecified are ignored. */ export interface QueryFilters { /** * Filter to active queries, inactive queries or all queries + * * @defaultValue 'all' */ type?: QueryTypeFilter - /** - * Match query key exactly - */ + /** Match query key exactly */ exact?: boolean - /** - * Include queries matching this predicate function - */ + /** Include queries matching this predicate function */ predicate?: (query: Query) => boolean - /** - * Include queries matching this query key - */ + /** Include queries matching this query key */ queryKey?: TQueryKey | TuplePrefixes - /** - * Include or exclude stale queries - */ + /** Include or exclude stale queries */ stale?: boolean - /** - * Include queries matching their fetchStatus - */ + /** Include queries matching their fetchStatus */ fetchStatus?: FetchStatus } /** - * Filters used to select mutations, for example in `mutationCache.findAll` or `queryClient.isMutating`. - * All provided filters must match; filters that are left unspecified are ignored. + * Filters used to select mutations, for example in `mutationCache.findAll` or + * `queryClient.isMutating`. All provided filters must match; filters that are + * left unspecified are ignored. */ export interface MutationFilters< TData = unknown, @@ -66,66 +59,58 @@ export interface MutationFilters< TVariables = unknown, TOnMutateResult = unknown, > { - /** - * Match mutation key exactly - */ + /** Match mutation key exactly */ exact?: boolean - /** - * Include mutations matching this predicate function - */ + /** Include mutations matching this predicate function */ predicate?: ( mutation: Mutation, ) => boolean - /** - * Include mutations matching this mutation key - */ + /** Include mutations matching this mutation key */ mutationKey?: TuplePrefixes - /** - * Filter by mutation status - */ + /** Filter by mutation status */ status?: MutationStatus } /** - * Either a plain value of type `TOutput`, or a function that receives `TInput` and returns `TOutput`. - * Used for example by `setQueryData`-style updaters, which accept either the new data directly or a - * function that computes it from the previous data. See {@link functionalUpdate}. + * Either a plain value of type `TOutput`, or a function that receives `TInput` + * and returns `TOutput`. Used for example by `setQueryData`-style updaters, + * which accept either the new data directly or a function that computes it from + * the previous data. See {@link functionalUpdate}. + * * @example - * ```ts - * queryClient.setQueryData(['posts'], newPosts) - * - * // Or, using an updater function that receives the current data: - * queryClient.setQueryData(['posts'], (oldPosts) => - * oldPosts ? [...oldPosts, newPost] : oldPosts, - * ) - * ``` + * ```ts + * queryClient.setQueryData(['posts'], newPosts) + * + * // Or, using an updater function that receives the current data: + * queryClient.setQueryData(['posts'], (oldPosts) => + * oldPosts ? [...oldPosts, newPost] : oldPosts, + * ) + * ``` */ export type Updater = TOutput | ((input: TInput) => TOutput) /** - * Which queries a filter matches: all of them, only active ones (with enabled observers), or only - * inactive ones. + * Which queries a filter matches: all of them, only active ones (with enabled + * observers), or only inactive ones. */ export type QueryTypeFilter = 'all' | 'active' | 'inactive' // UTILS -/** - * @deprecated use `environmentManager.isServer()` instead. - */ +/** @deprecated use `environmentManager.isServer()` instead. */ export const isServer = typeof window === 'undefined' || 'Deno' in globalThis -/** - * A function that does nothing. - */ +/** A function that does nothing. */ export function noop(): void export function noop(): undefined export function noop() {} /** - * Resolves an {@link Updater}: calls it with `input` if it is a function, otherwise returns it as - * is. - * @param updater - The new value, or a function that receives `input` and returns the new value. + * Resolves an {@link Updater}: calls it with `input` if it is a function, + * otherwise returns it as is. + * + * @param updater - The new value, or a function that receives `input` and + * returns the new value. * @param input - The current value, passed to `updater` if it is a function. * @returns The new value. */ @@ -139,7 +124,9 @@ export function functionalUpdate( } /** - * Checks whether a value can be used as a timeout: a non-negative, finite number. + * Checks whether a value can be used as a timeout: a non-negative, finite + * number. + * * @param value - The value to check. * @returns `true` if `value` is a number that is `>= 0` and not `Infinity`. */ @@ -149,19 +136,24 @@ export function isValidTimeout(value: unknown): value is number { /** * Calculates how long until data updated at `updatedAt` becomes stale. - * @param updatedAt - The timestamp, in milliseconds, at which the data was last updated. - * @param staleTime - The time, in milliseconds, after which data is considered stale. Defaults to - * `0`. - * @returns The remaining time in milliseconds, or `0` if the data is already stale. + * + * @param updatedAt - The timestamp, in milliseconds, at which the data was last + * updated. + * @param staleTime - The time, in milliseconds, after which data is considered + * stale. Defaults to `0`. + * @returns The remaining time in milliseconds, or `0` if the data is already + * stale. */ export function timeUntilStale(updatedAt: number, staleTime?: number): number { return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0) } /** - * Resolves an option that can be given either as a value or as a function of the query, such as - * `staleTime`. - * @param value - The option value, or a function that receives `query` and returns the value. + * Resolves an option that can be given either as a value or as a function of + * the query, such as `staleTime`. + * + * @param value - The option value, or a function that receives `query` and + * returns the value. * @param query - The query passed to `value` if it is a function. * @returns The resolved value, or `undefined` if `value` is `undefined`. */ @@ -188,19 +180,21 @@ export function resolveQueryValue< } /** - * Checks whether a query matches the given {@link QueryFilters}. - * Every filter that is specified must match; filters that are left unspecified are ignored. + * Checks whether a query matches the given {@link QueryFilters}. Every filter + * that is specified must match; filters that are left unspecified are ignored. + * + * @example + * ```ts + * const queryCache = queryClient.getQueryCache() + * + * const matchingQueries = queryCache + * .getAll() + * .filter((query) => matchQuery({ queryKey: ['posts'] }, query)) + * ``` + * * @param filters - The filters to check the query against. * @param query - The query to check. * @returns `true` if the query matches every specified filter. - * @example - * ```ts - * const queryCache = queryClient.getQueryCache() - * - * const matchingQueries = queryCache - * .getAll() - * .filter((query) => matchQuery({ queryKey: ['posts'] }, query)) - * ``` */ export function matchQuery( filters: QueryFilters, @@ -251,20 +245,25 @@ export function matchQuery( } /** - * Checks whether a mutation matches the given {@link MutationFilters}. - * Every filter that is specified must match; filters that are left unspecified are ignored. - * If a `mutationKey` filter is provided but the mutation has no `mutationKey` of its own, it does not match. + * Checks whether a mutation matches the given {@link MutationFilters}. Every + * filter that is specified must match; filters that are left unspecified are + * ignored. If a `mutationKey` filter is provided but the mutation has no + * `mutationKey` of its own, it does not match. + * + * @example + * ```ts + * const mutationCache = queryClient.getMutationCache() + * + * const matchingMutations = mutationCache + * .getAll() + * .filter((mutation) => + * matchMutation({ mutationKey: ['addPost'] }, mutation), + * ) + * ``` + * * @param filters - The filters to check the mutation against. * @param mutation - The mutation to check. * @returns `true` if the mutation matches every specified filter. - * @example - * ```ts - * const mutationCache = queryClient.getMutationCache() - * - * const matchingMutations = mutationCache - * .getAll() - * .filter((mutation) => matchMutation({ mutationKey: ['addPost'] }, mutation)) - * ``` */ export function matchMutation( filters: MutationFilters, @@ -296,9 +295,12 @@ export function matchMutation( } /** - * Hashes a query key with the query's `queryKeyHashFn` option, falling back to {@link hashKey}. + * Hashes a query key with the query's `queryKeyHashFn` option, falling back to + * {@link hashKey}. + * * @param queryKey - The query key to hash. - * @param options - The query options that may provide a custom `queryKeyHashFn`. + * @param options - The query options that may provide a custom + * `queryKeyHashFn`. * @returns The query hash, a string that identifies the query in the cache. */ export function hashQueryKeyByOptions( @@ -310,15 +312,17 @@ export function hashQueryKeyByOptions( } /** - * Default query & mutation keys hash function. - * Hashes the value into a stable hash. + * Default query & mutation keys hash function. Hashes the value into a stable + * hash. + * + * @example + * ```ts + * // Object keys are sorted, so key order doesn't affect the hash: + * hashKey(['todos', { page: 1, filter: 'done' }]) // === '["todos",{"filter":"done","page":1}]' + * ``` + * * @param queryKey - The query or mutation key to hash. * @returns The stable hash of the key, as a JSON string. - * @example - * ```ts - * // Object keys are sorted, so key order doesn't affect the hash: - * hashKey(['todos', { page: 1, filter: 'done' }]) // === '["todos",{"filter":"done","page":1}]' - * ``` */ export function hashKey(queryKey: QueryKey | MutationKey): string { return JSON.stringify(queryKey, (_, val) => @@ -335,10 +339,11 @@ export function hashKey(queryKey: QueryKey | MutationKey): string { /** * Checks if key `b` partially matches with key `a`. + * * @param a - The key to check, e.g. a query's own key. * @param b - The (partial) key to match against `a`. - * @returns `true` if every array element or object property in `b` matches the one at the same - * position in `a`. + * @returns `true` if every array element or object property in `b` matches the + * one at the same position in `a`. */ export function partialMatchKey(a: QueryKey, b: QueryKey): boolean export function partialMatchKey(a: any, b: any): boolean { @@ -376,14 +381,16 @@ export function partialMatchKey(a: any, b: any): boolean { const hasOwn = Object.prototype.hasOwnProperty /** - * This function returns `a` if `b` is deeply equal. - * If not, it will replace any deeply equal children of `b` with those of `a`. - * This can be used for structural sharing between JSON values for example. + * This function returns `a` if `b` is deeply equal. If not, it will replace any + * deeply equal children of `b` with those of `a`. This can be used for + * structural sharing between JSON values for example. + * * @param a - The previous value, whose deeply equal parts are reused. * @param b - The new value. - * @param depth - The current recursion depth. Past a depth of `500`, `b` is returned as is. - * @returns `a` if `b` is deeply equal to it, otherwise `b` with its deeply equal parts replaced by - * those of `a`. + * @param depth - The current recursion depth. Past a depth of `500`, `b` is + * returned as is. + * @returns `a` if `b` is deeply equal to it, otherwise `b` with its deeply + * equal parts replaced by those of `a`. */ export function replaceEqualDeep(a: unknown, b: T, depth?: number): T export function replaceEqualDeep(a: any, b: any, depth = 0): any { @@ -436,9 +443,11 @@ export function replaceEqualDeep(a: any, b: any, depth = 0): any { /** * Shallow compare objects. + * * @param a - The first object. * @param b - The second object, or `undefined`. - * @returns `true` if both objects have the same keys, with strictly equal values for each key. + * @returns `true` if both objects have the same keys, with strictly equal + * values for each key. */ export function shallowEqualObjects>( a: T, @@ -459,8 +468,10 @@ export function shallowEqualObjects>( /** * Checks whether a value is an array with no holes and no extra properties. + * * @param value - The value to check. - * @returns `true` if `value` is an array whose number of own keys equals its `length`. + * @returns `true` if `value` is an array whose number of own keys equals its + * `length`. */ export function isPlainArray(value: unknown): value is Array { return Array.isArray(value) && value.length === Object.keys(value).length @@ -468,8 +479,9 @@ export function isPlainArray(value: unknown): value is Array { // Copied from: https://github.com/jonschlinkert/is-plain-object /** - * Checks whether a value is a plain object, e.g. created with an object literal or - * `Object.create(null)`. + * Checks whether a value is a plain object, e.g. created with an object literal + * or `Object.create(null)`. + * * @param o - The value to check. * @returns `true` if `o` is a plain object. */ @@ -510,7 +522,9 @@ export function isPlainObject(o: any): o is Record { } /** - * Checks whether a value's `Object.prototype.toString` tag is `[object Object]`. + * Checks whether a value's `Object.prototype.toString` tag is `[object + * Object]`. + * * @param o - The value to check. * @returns `true` if the tag is `[object Object]`. */ @@ -520,6 +534,7 @@ function hasObjectPrototype(o: any): boolean { /** * Waits for the given time, using the configured {@link timeoutManager}. + * * @param timeout - The time to wait, in milliseconds. * @returns A promise that resolves after `timeout` milliseconds. */ @@ -531,13 +546,17 @@ export function sleep(timeout: number): Promise { /** * Applies a query's `structuralSharing` option when writing new data. + * * @param prevData - The previously cached data. * @param data - The new data. - * @param options - The query options, whose `structuralSharing` decides how the data is merged. - * @returns The result of a custom `structuralSharing` function, `data` with its unchanged parts - * replaced by those of `prevData` by default, or `data` as is if `structuralSharing` is `false`. - * @throws {Error} The error from the default structural sharing, e.g. when the data is not JSON serializable. - * Outside production, it is also logged to the console. + * @param options - The query options, whose `structuralSharing` decides how the + * data is merged. + * @returns The result of a custom `structuralSharing` function, `data` with its + * unchanged parts replaced by those of `prevData` by default, or `data` as is + * if `structuralSharing` is `false`. + * @throws {Error} The error from the default structural sharing, e.g. when the + * data is not JSON serializable. Outside production, it is also logged to the + * console. */ export function replaceData< TData, @@ -566,18 +585,22 @@ export function replaceData< /** * Intended to be passed as a query's `placeholderData` option, for example - * `placeholderData: keepPreviousData`. Instead of resetting the query's data to `undefined` while a new - * query key is fetching, it keeps displaying the previously fetched data until the new data arrives. - * @param previousData - The data of the previous query key, passed by the observer. - * @returns The previous data, unchanged. + * `placeholderData: keepPreviousData`. Instead of resetting the query's data to + * `undefined` while a new query key is fetching, it keeps displaying the + * previously fetched data until the new data arrives. + * * @example - * ```ts - * new QueryObserver(queryClient, { - * queryKey: ['posts', page], - * queryFn: () => fetchPosts(page), - * placeholderData: keepPreviousData, - * }) - * ``` + * ```ts + * new QueryObserver(queryClient, { + * queryKey: ['posts', page], + * queryFn: () => fetchPosts(page), + * placeholderData: keepPreviousData, + * }) + * ``` + * + * @param previousData - The data of the previous query key, passed by the + * observer. + * @returns The previous data, unchanged. */ export function keepPreviousData( previousData: T | undefined, @@ -586,12 +609,14 @@ export function keepPreviousData( } /** - * Returns a new array with `item` added at the end. If that makes the array longer than `max`, - * the first item is dropped. Only one item is dropped, so the result can still exceed `max` if - * `items` already did. + * Returns a new array with `item` added at the end. If that makes the array + * longer than `max`, the first item is dropped. Only one item is dropped, so + * the result can still exceed `max` if `items` already did. + * * @param items - The current items. * @param item - The value to append. - * @param max - The length above which an item is dropped. `0` (the default) means no limit. + * @param max - The length above which an item is dropped. `0` (the default) + * means no limit. * @returns A new array with `item` added. */ export function addToEnd(items: Array, item: T, max = 0): Array { @@ -600,12 +625,14 @@ export function addToEnd(items: Array, item: T, max = 0): Array { } /** - * Returns a new array with `item` added at the start. If that makes the array longer than `max`, - * the last item is dropped. Only one item is dropped, so the result can still exceed `max` if - * `items` already did. + * Returns a new array with `item` added at the start. If that makes the array + * longer than `max`, the last item is dropped. Only one item is dropped, so the + * result can still exceed `max` if `items` already did. + * * @param items - The current items. * @param item - The value to prepend. - * @param max - The length above which an item is dropped. `0` (the default) means no limit. + * @param max - The length above which an item is dropped. `0` (the default) + * means no limit. * @returns A new array with `item` added. */ export function addToStart(items: Array, item: T, max = 0): Array { @@ -614,28 +641,31 @@ export function addToStart(items: Array, item: T, max = 0): Array { } /** - * Sentinel value that can be passed as a query's `queryFn` to conditionally disable the query (equivalent - * to `enabled: false`) while preserving full type inference for the query's data. Unlike `enabled: false`, - * a query disabled via `skipToken` cannot be triggered with `refetch`. + * Sentinel value that can be passed as a query's `queryFn` to conditionally + * disable the query (equivalent to `enabled: false`) while preserving full type + * inference for the query's data. Unlike `enabled: false`, a query disabled via + * `skipToken` cannot be triggered with `refetch`. + * * @example - * ```ts - * new QueryObserver(queryClient, { - * queryKey: ['post', postId], - * queryFn: postId != null ? () => fetchPost(postId) : skipToken, - * }) - * ``` + * ```ts + * new QueryObserver(queryClient, { + * queryKey: ['post', postId], + * queryFn: postId != null ? () => fetchPost(postId) : skipToken, + * }) + * ``` */ export const skipToken = Symbol() -/** - * The type of the {@link skipToken} sentinel value. - */ +/** The type of the {@link skipToken} sentinel value. */ export type SkipToken = typeof skipToken /** - * Returns the function to call for a fetch. If there is no `queryFn` but the fetch was started from - * an `initialPromise`, that promise is returned instead. If there is no usable `queryFn` (missing or - * {@link skipToken}), the returned function rejects with a `Missing queryFn` error. - * @param options - The query options with the `queryFn`, and the `queryHash` used in error messages. + * Returns the function to call for a fetch. If there is no `queryFn` but the + * fetch was started from an `initialPromise`, that promise is returned instead. + * If there is no usable `queryFn` (missing or {@link skipToken}), the returned + * function rejects with a `Missing queryFn` error. + * + * @param options - The query options with the `queryFn`, and the `queryHash` + * used in error messages. * @param fetchOptions - The fetch options, which may carry an `initialPromise`. * @returns The function to call for the fetch. */ @@ -673,22 +703,25 @@ export function ensureQueryFn< } /** - * Resolves a `throwOnError` option to a boolean. - * If `throwOnError` is a function, it is called with `params` (e.g. the error and, depending on the caller, - * additional context such as the query or mutation) and its result is returned, allowing the throwing - * behavior to be decided per error. Otherwise, `throwOnError` itself is coerced to a boolean (`undefined` - * resolves to `false`). - * @param throwOnError - The `throwOnError` option: a boolean, a function that decides per error, or - * `undefined`. + * Resolves a `throwOnError` option to a boolean. If `throwOnError` is a + * function, it is called with `params` (e.g. the error and, depending on the + * caller, additional context such as the query or mutation) and its result is + * returned, allowing the throwing behavior to be decided per error. Otherwise, + * `throwOnError` itself is coerced to a boolean (`undefined` resolves to + * `false`). + * + * @example + * ```ts + * const throwOnError = + * query.state.error && typeof options.throwOnError === 'function' + * ? shouldThrowError(options.throwOnError, [query.state.error, query]) + * : options.throwOnError + * ``` + * + * @param throwOnError - The `throwOnError` option: a boolean, a function that + * decides per error, or `undefined`. * @param params - The arguments passed to `throwOnError` if it is a function. * @returns Whether the error should be thrown. - * @example - * ```ts - * const throwOnError = - * query.state.error && typeof options.throwOnError === 'function' - * ? shouldThrowError(options.throwOnError, [query.state.error, query]) - * : options.throwOnError - * ``` */ export function shouldThrowError) => boolean>( throwOnError: boolean | T | undefined, @@ -703,11 +736,14 @@ export function shouldThrowError) => boolean>( } /** - * Adds a lazy `signal` getter to an object, such as a query function context. The first time - * `signal` is read, `onCancelled` is registered for the signal's `abort` event (or called right - * away if it is already aborted), so cancellation is only tracked when the signal is actually used. + * Adds a lazy `signal` getter to an object, such as a query function context. + * The first time `signal` is read, `onCancelled` is registered for the signal's + * `abort` event (or called right away if it is already aborted), so + * cancellation is only tracked when the signal is actually used. + * * @param object - The object to add the `signal` property to. - * @param getSignal - Returns the `AbortSignal`. Called once, when `signal` is first read. + * @param getSignal - Returns the `AbortSignal`. Called once, when `signal` is + * first read. * @param onCancelled - Called when the signal is aborted, if `signal` was read. * @returns The same object, with the `signal` property added. */ diff --git a/packages/query-devtools/src/Devtools.tsx b/packages/query-devtools/src/Devtools.tsx index c13e017377e..dbd9c867f0e 100644 --- a/packages/query-devtools/src/Devtools.tsx +++ b/packages/query-devtools/src/Devtools.tsx @@ -102,8 +102,8 @@ interface QueryStatusProps { } /** - * The devtools component that `TanstackQueryDevtools` and `TanstackQueryDevtoolsPanel` lazily load - * and render. + * The devtools component that `TanstackQueryDevtools` and + * `TanstackQueryDevtoolsPanel` lazily load and render. */ export type DevtoolsComponentType = Component & { shadowDOMTarget?: ShadowRoot @@ -112,8 +112,9 @@ export type DevtoolsComponentType = Component & { /** * The floating devtools: a toggle button that opens a resizable panel, or the * panel in a picture-in-picture window when one is open. + * * @param props - The `localStore` that persists the devtools settings, and its - * `setLocalStore` setter. + * `setLocalStore` setter. * @returns The toggle button and the panel. */ export const Devtools: Component = (props) => { @@ -347,8 +348,9 @@ const PiPPanel: Component<{ } /** - * The container of the embedded devtools panel, which tracks its width for - * the responsive layout. + * The container of the embedded devtools panel, which tracks its width for the + * responsive layout. + * * @param props - The `children` to render inside the panel. * @returns The panel container. */ @@ -682,9 +684,10 @@ const DraggablePanel: Component = (props) => { /** * The content of the devtools panel: the query and mutation lists with their * filters and actions, and the details of the selected query or mutation. + * * @param props - The `localStore` and `setLocalStore` that persist the devtools - * settings, `showPanelViewOnly` to hide the controls that only apply to the - * floating devtools, and `onClose` to close an embedded panel. + * settings, `showPanelViewOnly` to hide the controls that only apply to the + * floating devtools, and `onClose` to close an embedded panel. * @returns The panel content. */ export const ContentView: Component = (props) => { diff --git a/packages/query-devtools/src/Explorer.tsx b/packages/query-devtools/src/Explorer.tsx index 81a042f762d..970ae806863 100644 --- a/packages/query-devtools/src/Explorer.tsx +++ b/packages/query-devtools/src/Explorer.tsx @@ -34,11 +34,14 @@ import type { Query } from '@tanstack/query-core' * * When the array cannot be chunked evenly by size, the last chunk will be * filled with the remaining elements. + * + * @example + * chunkArray(['a', 'b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']] + * * @param array - The elements to chunk. - * @param size - The number of elements per chunk. Below `1`, no chunks are returned. + * @param size - The number of elements per chunk. Below `1`, no chunks are + * returned. * @returns The chunks. - * @example - * chunkArray(['a','b', 'c', 'd', 'e'], 2) // returns [['a','b'], ['c', 'd'], ['e']] */ function chunkArray( array: Array, @@ -267,6 +270,7 @@ type ExplorerProps = { /** * Checks whether a value is iterable. + * * @param x - The value to check. * @returns `true` if `x` has a `Symbol.iterator` method. */ @@ -275,10 +279,11 @@ function isIterable(x: any): x is Iterable { } /** - * Renders an expandable tree view of a value, used to explore a query's data in the devtools. It - * can also edit and delete entries in the query's data. - * @param props - The value to show and its label, plus the options for expanding, editing, and - * deleting entries. + * Renders an expandable tree view of a value, used to explore a query's data in + * the devtools. It can also edit and delete entries in the query's data. + * + * @param props - The value to show and its label, plus the options for + * expanding, editing, and deleting entries. * @returns The tree view. */ export default function Explorer(props: ExplorerProps) { diff --git a/packages/query-devtools/src/TanstackQueryDevtools.tsx b/packages/query-devtools/src/TanstackQueryDevtools.tsx index d6bf39b2e66..b2fb990099e 100644 --- a/packages/query-devtools/src/TanstackQueryDevtools.tsx +++ b/packages/query-devtools/src/TanstackQueryDevtools.tsx @@ -15,18 +15,18 @@ import type { } from './contexts/types' import type { Signal } from 'solid-js' -/** - * The options for `TanstackQueryDevtools`, which mounts the floating devtools. - */ +/** The options for `TanstackQueryDevtools`, which mounts the floating devtools. */ export interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps { /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if - * you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot } diff --git a/packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx b/packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx index da2557beda5..53d5f258df0 100644 --- a/packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx +++ b/packages/query-devtools/src/TanstackQueryDevtoolsPanel.tsx @@ -16,22 +16,23 @@ import type { import type { Signal } from 'solid-js' /** - * The options for `TanstackQueryDevtoolsPanel`, which mounts the devtools as an embedded panel. + * The options for `TanstackQueryDevtoolsPanel`, which mounts the devtools as an + * embedded panel. */ export interface TanstackQueryDevtoolsPanelConfig extends QueryDevtoolsProps { /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if - * you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Callback function that is called when the devtools panel is closed. - */ + /** Callback function that is called when the devtools panel is closed. */ onClose?: () => void } diff --git a/packages/query-devtools/src/contexts/DevtoolsOfflineContext.ts b/packages/query-devtools/src/contexts/DevtoolsOfflineContext.ts index 384a73d1f9c..33065372bd0 100644 --- a/packages/query-devtools/src/contexts/DevtoolsOfflineContext.ts +++ b/packages/query-devtools/src/contexts/DevtoolsOfflineContext.ts @@ -5,6 +5,7 @@ export const DevtoolsOfflineContext = createContext() /** * Returns the devtools offline state provided by `DevtoolsOfflineProvider`. + * * @returns The offline state. * @throws {Error} If there is no `DevtoolsOfflineProvider` above. */ diff --git a/packages/query-devtools/src/contexts/DevtoolsStateContext.ts b/packages/query-devtools/src/contexts/DevtoolsStateContext.ts index ee89c2e8bc5..6bef5c3948f 100644 --- a/packages/query-devtools/src/contexts/DevtoolsStateContext.ts +++ b/packages/query-devtools/src/contexts/DevtoolsStateContext.ts @@ -4,7 +4,9 @@ import type { DevtoolsState } from './types' export const DevtoolsStateContext = createContext() /** - * Returns the devtools selection and panel state provided by `DevtoolsStateProvider`. + * Returns the devtools selection and panel state provided by + * `DevtoolsStateProvider`. + * * @returns The selection and panel state. * @throws {Error} If there is no `DevtoolsStateProvider` above. */ diff --git a/packages/query-devtools/src/contexts/DevtoolsSubscriptionsContext.ts b/packages/query-devtools/src/contexts/DevtoolsSubscriptionsContext.ts index f600530b833..6b3c98f8f91 100644 --- a/packages/query-devtools/src/contexts/DevtoolsSubscriptionsContext.ts +++ b/packages/query-devtools/src/contexts/DevtoolsSubscriptionsContext.ts @@ -5,7 +5,9 @@ export const DevtoolsSubscriptionsContext = createContext() /** - * Returns the devtools cache subscription registries provided by `DevtoolsSubscriptionsProvider`. + * Returns the devtools cache subscription registries provided by + * `DevtoolsSubscriptionsProvider`. + * * @returns The cache subscription registries. * @throws {Error} If there is no `DevtoolsSubscriptionsProvider` above. */ diff --git a/packages/query-devtools/src/contexts/PiPContext.tsx b/packages/query-devtools/src/contexts/PiPContext.tsx index 1529eea9345..ed12c02fdec 100644 --- a/packages/query-devtools/src/contexts/PiPContext.tsx +++ b/packages/query-devtools/src/contexts/PiPContext.tsx @@ -33,11 +33,12 @@ const PiPContext = createContext | undefined>( ) /** - * Provides the picture-in-picture window of the devtools, and functions to - * open and close it. - * @param props - The `children` to render, the `localStore` and - * `setLocalStore` that persist whether the window is open, and `disabled` to - * turn picture-in-picture off. + * Provides the picture-in-picture window of the devtools, and functions to open + * and close it. + * + * @param props - The `children` to render, the `localStore` and `setLocalStore` + * that persist whether the window is open, and `disabled` to turn + * picture-in-picture off. * @returns The context provider. */ export const PiPProvider = (props: PiPProviderProps) => { @@ -202,8 +203,9 @@ export const PiPProvider = (props: PiPProviderProps) => { /** * Reads the picture-in-picture context provided by {@link PiPProvider}. + * * @returns An accessor of the picture-in-picture window and the functions to - * open and close it. + * open and close it. */ export const usePiPWindow = () => { const context = createMemo(() => { diff --git a/packages/query-devtools/src/contexts/QueryDevtoolsContext.ts b/packages/query-devtools/src/contexts/QueryDevtoolsContext.ts index 8c52388a8ec..fd4f2fd57d3 100644 --- a/packages/query-devtools/src/contexts/QueryDevtoolsContext.ts +++ b/packages/query-devtools/src/contexts/QueryDevtoolsContext.ts @@ -19,7 +19,9 @@ export const QueryDevtoolsContext = createContext({ }) /** - * Returns the devtools configuration from context, such as the `client` and the `onlineManager`. + * Returns the devtools configuration from context, such as the `client` and the + * `onlineManager`. + * * @returns The devtools configuration. */ export function useQueryDevtoolsContext() { diff --git a/packages/query-devtools/src/contexts/ThemeContext.ts b/packages/query-devtools/src/contexts/ThemeContext.ts index ebcfcd49239..e1f5e891de0 100644 --- a/packages/query-devtools/src/contexts/ThemeContext.ts +++ b/packages/query-devtools/src/contexts/ThemeContext.ts @@ -7,7 +7,9 @@ export const ThemeContext = createContext>( /** * Returns the devtools theme from context. - * @returns A getter for the current theme, `'light'` or `'dark'`. Defaults to `'dark'`. + * + * @returns A getter for the current theme, `'light'` or `'dark'`. Defaults to + * `'dark'`. */ export function useTheme() { return useContext(ThemeContext) diff --git a/packages/query-devtools/src/contexts/types.ts b/packages/query-devtools/src/contexts/types.ts index 2245605849d..7dbdf1244ff 100644 --- a/packages/query-devtools/src/contexts/types.ts +++ b/packages/query-devtools/src/contexts/types.ts @@ -13,136 +13,117 @@ import type { createCacheSubscriptionRegistry } from '../createCacheSubscription type XPosition = 'left' | 'right' type YPosition = 'top' | 'bottom' -/** - * The side of the screen the devtools panel opens on. - */ +/** The side of the screen the devtools panel opens on. */ export type DevtoolsPosition = XPosition | YPosition /** - * The corner of the screen the toggle button is placed in, or `'relative'` to place it in the - * normal document flow. + * The corner of the screen the toggle button is placed in, or `'relative'` to + * place it in the normal document flow. */ export type DevtoolsButtonPosition = `${YPosition}-${XPosition}` | 'relative' /** - * The color theme of the devtools. `'system'` follows the user's color scheme preference. + * The color theme of the devtools. `'system'` follows the user's color scheme + * preference. */ export type Theme = 'dark' | 'light' | 'system' -/** - * A custom error that can be triggered on a query from the devtools. - */ +/** A custom error that can be triggered on a query from the devtools. */ export interface DevtoolsErrorType { - /** - * The name of the error. - */ + /** The name of the error. */ name: string - /** - * How the error is initialized. - */ + /** How the error is initialized. */ initializer: (query: Query) => Error } /** - * The options shared by every devtools entry point: the `client` to inspect, the adapter's - * `queryFlavor` and `version` shown in the header, and the display options. - * `onClose` is only used by the panel entry point. + * The options shared by every devtools entry point: the `client` to inspect, + * the adapter's `queryFlavor` and `version` shown in the header, and the + * display options. `onClose` is only used by the panel entry point. */ export interface QueryDevtoolsProps { - /** - * The `QueryClient` whose caches the devtools inspect. - */ + /** The `QueryClient` whose caches the devtools inspect. */ readonly client: QueryClient /** - * The adapter name shown next to the logo in the header, e.g. `'React Query'`. + * The adapter name shown next to the logo in the header, e.g. `'React + * Query'`. */ queryFlavor: string - /** - * The adapter version shown next to `queryFlavor` in the header. - */ + /** The adapter version shown next to `queryFlavor` in the header. */ version: string - /** - * The `onlineManager` the devtools read and toggle to simulate going offline. - */ + /** The `onlineManager` the devtools read and toggle to simulate going offline. */ onlineManager: typeof onlineManager - /** - * The position of the TanStack logo to open and close the devtools panel. - */ + /** The position of the TanStack logo to open and close the devtools panel. */ buttonPosition?: DevtoolsButtonPosition - /** - * The position of the devtools panel. - */ + /** The position of the devtools panel. */ position?: DevtoolsPosition - /** - * Set this to `true` if you want the devtools to default to being open. - */ + /** Set this to `true` if you want the devtools to default to being open. */ initialIsOpen?: boolean - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot /** - * Callback function that is called when the devtools panel is closed. Only used by the panel - * entry point. + * Callback function that is called when the devtools panel is closed. Only + * used by the panel entry point. */ onClose?: () => void - /** - * Set this to `true` to hide disabled queries from the devtools panel. - */ + /** Set this to `true` to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to `'light'`, `'dark'`, or `'system'` to change the theme of the devtools panel. + * Set this to `'light'`, `'dark'`, or `'system'` to change the theme of the + * devtools panel. */ theme?: Theme } -/** - * The devtools UI state: the selected query and mutation, and the panel width. - */ +/** The devtools UI state: the selected query and mutation, and the panel width. */ export interface DevtoolsState { /** - * The hash of the query whose details are shown, or `null` if none is selected. + * The hash of the query whose details are shown, or `null` if none is + * selected. */ selectedQueryHash: Accessor - /** - * Selects a query by its hash, or clears the selection with `null`. - */ + /** Selects a query by its hash, or clears the selection with `null`. */ setSelectedQueryHash: Setter /** - * The `mutationId` of the mutation whose details are shown, or `null` if none is selected. + * The `mutationId` of the mutation whose details are shown, or `null` if none + * is selected. */ selectedMutationId: Accessor /** - * Selects a mutation by its `mutationId`, or clears the selection with `null`. + * Selects a mutation by its `mutationId`, or clears the selection with + * `null`. */ setSelectedMutationId: Setter /** - * The current width of the devtools panel in pixels, used for the responsive layout. + * The current width of the devtools panel in pixels, used for the responsive + * layout. */ panelWidth: Accessor - /** - * Updates the stored panel width, e.g. when the panel is resized. - */ + /** Updates the stored panel width, e.g. when the panel is resized. */ setPanelWidth: Setter } /** - * The registries through which devtools components subscribe to the query cache and the mutation - * cache, each one only updating for the cache events it cares about. + * The registries through which devtools components subscribe to the query cache + * and the mutation cache, each one only updating for the cache events it cares + * about. */ export interface DevtoolsSubscriptions { /** - * The registry through which devtools components subscribe to query cache events. + * The registry through which devtools components subscribe to query cache + * events. */ queryCacheSubscriptions: ReturnType< typeof createCacheSubscriptionRegistry > /** - * The registry through which devtools components subscribe to mutation cache events. + * The registry through which devtools components subscribe to mutation cache + * events. */ mutationCacheSubscriptions: ReturnType< typeof createCacheSubscriptionRegistry< @@ -153,15 +134,12 @@ export interface DevtoolsSubscriptions { } /** - * Whether the devtools' `onlineManager` is offline, and a function that toggles it. + * Whether the devtools' `onlineManager` is offline, and a function that toggles + * it. */ export interface DevtoolsOfflineState { - /** - * Whether the devtools' `onlineManager` is currently offline. - */ + /** Whether the devtools' `onlineManager` is currently offline. */ offline: Accessor - /** - * Switches the devtools' `onlineManager` between online and offline. - */ + /** Switches the devtools' `onlineManager` between online and offline. */ toggleOffline: () => void } diff --git a/packages/query-devtools/src/createCacheSubscriptionRegistry.ts b/packages/query-devtools/src/createCacheSubscriptionRegistry.ts index 66029a3d379..c71b3ecf2c5 100644 --- a/packages/query-devtools/src/createCacheSubscriptionRegistry.ts +++ b/packages/query-devtools/src/createCacheSubscriptionRegistry.ts @@ -2,8 +2,9 @@ import { onCleanup } from 'solid-js' import type { Accessor, Setter } from 'solid-js' /** - * Creates a registry of components subscribed to a cache, so each one only updates for the cache - * events it cares about. + * Creates a registry of components subscribed to a cache, so each one only + * updates for the cache events it cares about. + * * @returns The `register` and `notify` functions of the registry. */ export function createCacheSubscriptionRegistry() { @@ -16,11 +17,13 @@ export function createCacheSubscriptionRegistry() { >() /** - * Registers a subscription that is removed when the current owner is cleaned up. + * Registers a subscription that is removed when the current owner is cleaned + * up. + * * @param callback - Computes the value from the cache. * @param setter - Receives the computed value on every update. - * @param shouldUpdate - Decides whether an event updates this subscription. Defaults to every - * event. + * @param shouldUpdate - Decides whether an event updates this subscription. + * Defaults to every event. */ function register( callback: (cache: Accessor) => Exclude, @@ -37,6 +40,7 @@ export function createCacheSubscriptionRegistry() { /** * Updates every subscription whose `shouldUpdate` accepts the event. + * * @param cache - The cache to compute the values from. * @param event - The cache event. * @param schedule - Runs each update. Defaults to running it right away. diff --git a/packages/query-devtools/src/icons/index.tsx b/packages/query-devtools/src/icons/index.tsx index 345b4d87ba4..04db718b193 100644 --- a/packages/query-devtools/src/icons/index.tsx +++ b/packages/query-devtools/src/icons/index.tsx @@ -2,6 +2,7 @@ import { Show, createUniqueId } from 'solid-js' /** * Renders the search icon. + * * @returns The icon's SVG element. */ export function Search() { @@ -26,6 +27,7 @@ export function Search() { /** * Renders the trash icon. + * * @returns The icon's SVG element. */ export function Trash() { @@ -50,6 +52,7 @@ export function Trash() { /** * Renders the chevron-down icon. + * * @returns The icon's SVG element. */ export function ChevronDown() { @@ -74,6 +77,7 @@ export function ChevronDown() { /** * Renders the up arrow icon. + * * @returns The icon's SVG element. */ export function ArrowUp() { @@ -98,6 +102,7 @@ export function ArrowUp() { /** * Renders the down arrow icon. + * * @returns The icon's SVG element. */ export function ArrowDown() { @@ -122,6 +127,7 @@ export function ArrowDown() { /** * Renders the left arrow icon. + * * @returns The icon's SVG element. */ export function ArrowLeft() { @@ -149,6 +155,7 @@ export function ArrowLeft() { /** * Renders the right arrow icon. + * * @returns The icon's SVG element. */ export function ArrowRight() { @@ -176,6 +183,7 @@ export function ArrowRight() { /** * Renders the sun (light theme) icon. + * * @returns The icon's SVG element. */ export function Sun() { @@ -200,6 +208,7 @@ export function Sun() { /** * Renders the moon (dark theme) icon. + * * @returns The icon's SVG element. */ export function Moon() { @@ -224,6 +233,7 @@ export function Moon() { /** * Renders the monitor (system theme) icon. + * * @returns The icon's SVG element. */ export function Monitor() { @@ -248,6 +258,7 @@ export function Monitor() { /** * Renders the Wi-Fi (online) icon. + * * @returns The icon's SVG element. */ export function Wifi() { @@ -269,6 +280,7 @@ export function Wifi() { /** * Renders the offline icon. + * * @returns The icon's SVG element. */ export function Offline() { @@ -291,6 +303,7 @@ export function Offline() { /** * Renders the settings icon. + * * @returns The icon's SVG element. */ export function Settings() { @@ -322,6 +335,7 @@ export function Settings() { /** * Renders the picture-in-picture icon. + * * @returns The icon's SVG element. */ export function PiPIcon() { @@ -346,6 +360,7 @@ export function PiPIcon() { /** * Renders the copy icon. + * * @returns The icon's SVG element. */ export function Copier() { @@ -371,6 +386,7 @@ export function Copier() { /** * Renders the pencil (edit) icon. + * * @returns The icon's SVG element. */ export function Pencil() { @@ -395,6 +411,7 @@ export function Pencil() { /** * Renders the icon shown after a value was copied. + * * @param props - The `theme` that decides the icon's color. * @returns The icon's SVG element. */ @@ -420,6 +437,7 @@ export function CopiedCopier(props: { theme: 'light' | 'dark' }) { /** * Renders the copy error icon. + * * @returns The icon's SVG element. */ export function ErrorCopier() { @@ -444,6 +462,7 @@ export function ErrorCopier() { /** * Renders the list icon. + * * @returns The icon's SVG element. */ export function List() { @@ -467,7 +486,9 @@ export function List() { /** * Renders a checkbox icon. - * @param props - Whether the checkbox is `checked`, and the `theme` that decides its color. + * + * @param props - Whether the checkbox is `checked`, and the `theme` that + * decides its color. * @returns The checked or unchecked checkbox icon. */ export function Check(props: { checked: boolean; theme: 'light' | 'dark' }) { @@ -513,6 +534,7 @@ export function Check(props: { checked: boolean; theme: 'light' | 'dark' }) { /** * Renders the check circle icon. + * * @returns The icon's SVG element. */ export function CheckCircle() { @@ -537,6 +559,7 @@ export function CheckCircle() { /** * Renders the loading circle icon. + * * @returns The icon's SVG element. */ export function LoadingCircle() { @@ -570,6 +593,7 @@ export function LoadingCircle() { /** * Renders the X circle icon. + * * @returns The icon's SVG element. */ export function XCircle() { @@ -594,6 +618,7 @@ export function XCircle() { /** * Renders the pause circle icon. + * * @returns The icon's SVG element. */ export function PauseCircle() { @@ -618,6 +643,7 @@ export function PauseCircle() { /** * Renders the TanStack logo. + * * @returns The logo's SVG element. */ export function TanstackLogo() { diff --git a/packages/query-devtools/src/providers/DevtoolsOfflineProvider.tsx b/packages/query-devtools/src/providers/DevtoolsOfflineProvider.tsx index 39cf45b7248..83eddd28021 100644 --- a/packages/query-devtools/src/providers/DevtoolsOfflineProvider.tsx +++ b/packages/query-devtools/src/providers/DevtoolsOfflineProvider.tsx @@ -5,8 +5,9 @@ import type { DevtoolsOfflineState } from '../contexts/types' import type { ParentProps } from 'solid-js' /** - * Provides its children with the offline state of the devtools `onlineManager`, and a function - * that toggles it. + * Provides its children with the offline state of the devtools `onlineManager`, + * and a function that toggles it. + * * @param props - The `children` to render. * @returns The `children`, wrapped in the context provider. */ diff --git a/packages/query-devtools/src/providers/DevtoolsStateProvider.tsx b/packages/query-devtools/src/providers/DevtoolsStateProvider.tsx index c249c9503e5..165c5112644 100644 --- a/packages/query-devtools/src/providers/DevtoolsStateProvider.tsx +++ b/packages/query-devtools/src/providers/DevtoolsStateProvider.tsx @@ -5,6 +5,7 @@ import type { ParentProps } from 'solid-js' /** * Provides the selected query and mutation and the panel width to its children. + * * @param props - The `children` to render. * @returns The `children`, wrapped in the context provider. */ diff --git a/packages/query-devtools/src/providers/DevtoolsSubscriptionsProvider.tsx b/packages/query-devtools/src/providers/DevtoolsSubscriptionsProvider.tsx index a551fe6b44f..e0f67b3a26e 100644 --- a/packages/query-devtools/src/providers/DevtoolsSubscriptionsProvider.tsx +++ b/packages/query-devtools/src/providers/DevtoolsSubscriptionsProvider.tsx @@ -10,7 +10,9 @@ import type { DevtoolsSubscriptions } from '../contexts/types' import type { ParentProps } from 'solid-js' /** - * Provides the query and mutation cache subscription registries to its children. + * Provides the query and mutation cache subscription registries to its + * children. + * * @param props - The `children` to render. * @returns The `children`, wrapped in the context provider. */ diff --git a/packages/query-devtools/src/utils.tsx b/packages/query-devtools/src/utils.tsx index 23b8df048b9..08ffab8fda7 100644 --- a/packages/query-devtools/src/utils.tsx +++ b/packages/query-devtools/src/utils.tsx @@ -4,10 +4,12 @@ import type { Mutation, Query } from '@tanstack/query-core' import type { DevtoolsPosition } from './contexts' /** - * Returns the status label of a query: fetching, inactive (no observers), paused, stale, or fresh, - * checked in that order. + * Returns the status label of a query: fetching, inactive (no observers), + * paused, stale, or fresh, checked in that order. + * * @param query - The query to label. - * @returns One of `'fetching'`, `'inactive'`, `'paused'`, `'stale'`, or `'fresh'`. + * @returns One of `'fetching'`, `'inactive'`, `'paused'`, `'stale'`, or + * `'fresh'`. */ export function getQueryStatusLabel(query: Query) { return query.state.fetchStatus === 'fetching' @@ -24,7 +26,9 @@ export function getQueryStatusLabel(query: Query) { type QueryStatusLabel = 'fresh' | 'stale' | 'paused' | 'inactive' | 'fetching' /** - * Appends a capitalized side to a CSS property name, e.g. `border` and `left` to `borderLeft`. + * Appends a capitalized side to a CSS property name, e.g. `border` and `left` + * to `borderLeft`. + * * @param prop - The property name. * @param side - The side to append. * @returns The sided property name. @@ -39,8 +43,9 @@ export function getSidedProp( } /** - * Returns the color of a query's status: blue while fetching, gray without observers, purple while - * paused, yellow when stale, otherwise green. + * Returns the color of a query's status: blue while fetching, gray without + * observers, purple while paused, yellow when stale, otherwise green. + * * @param params - The query's `queryState`, `observerCount`, and `isStale`. * @returns The color name. */ @@ -65,8 +70,9 @@ export function getQueryStatusColor({ } /** - * Returns the color of a mutation's status: purple while paused, red on error, yellow while pending, - * green on success, otherwise gray. + * Returns the color of a mutation's status: purple while paused, red on error, + * yellow while pending, green on success, otherwise gray. + * * @param params - The mutation's `status` and `isPaused`. * @returns The color name. */ @@ -90,6 +96,7 @@ export function getMutationStatusColor({ /** * Returns the color of a query status label. + * * @param label - A label returned by {@link getQueryStatusLabel}. * @returns The color name. */ @@ -107,6 +114,7 @@ export function getQueryStatusColorByLabel(label: QueryStatusLabel) { /** * Displays a string regardless of the type of the data. + * * @param value - Value to be stringified * @param beautify - Formats json to multiline * @returns The value serialized with `superjson`, as a JSON string. @@ -179,6 +187,7 @@ export const mutationSortFns: Record = { /** * Converts a length in `rem` to pixels, using the root element's font size. + * * @param rem - The length in `rem`. * @returns The length in pixels. */ @@ -188,8 +197,9 @@ export const convertRemToPixels = (rem: number) => { /** * Tracks the user's `prefers-color-scheme` setting. + * * @returns An accessor of `'light'` or `'dark'`, updated when the setting - * changes. + * changes. */ export const getPreferredColorScheme = () => { const [colorScheme, setColorScheme] = createSignal<'light' | 'dark'>('dark') @@ -209,6 +219,7 @@ export const getPreferredColorScheme = () => { /** * Updates nested data by path. + * * @param oldData - Data to be updated * @param updatePath - Path to the data to be updated * @param value - New value @@ -283,9 +294,10 @@ export const updateNestedDataByPath = ( /** * Deletes nested data by path. + * * @param oldData - Data to be updated * @param deletePath - Path to the data to be deleted - * @returns newData without the deleted items by path + * @returns NewData without the deleted items by path */ export const deleteNestedDataByPath = ( oldData: unknown, @@ -344,10 +356,13 @@ export const deleteNestedDataByPath = ( } /** - * Sets up the goober stylesheet with a `nonce`, for pages with a Content Security Policy. Without a - * `nonce`, it does nothing and goober creates the stylesheet itself. + * Sets up the goober stylesheet with a `nonce`, for pages with a Content + * Security Policy. Without a `nonce`, it does nothing and goober creates the + * stylesheet itself. + * * @param nonce - The nonce to set on the style tag. - * @param target - The shadow root to add the style tag to, instead of `document.head`. + * @param target - The shadow root to add the style tag to, instead of + * `document.head`. */ export const setupStyleSheet = (nonce?: string, target?: ShadowRoot) => { if (!nonce) diff --git a/packages/query-persist-client-core/src/createPersister.ts b/packages/query-persist-client-core/src/createPersister.ts index 323de9093b7..e48802014c4 100644 --- a/packages/query-persist-client-core/src/createPersister.ts +++ b/packages/query-persist-client-core/src/createPersister.ts @@ -13,72 +13,58 @@ import type { QueryState, } from '@tanstack/query-core' -/** - * A single query as stored by {@link experimental_createQueryPersister}. - */ +/** A single query as stored by {@link experimental_createQueryPersister}. */ export interface PersistedQuery { /** - * The `buster` the query was saved with. Entries with a different `buster` are discarded. + * The `buster` the query was saved with. Entries with a different `buster` + * are discarded. */ buster: string - /** - * The hash of the query. - */ + /** The hash of the query. */ queryHash: string - /** - * The key of the query. - */ + /** The key of the query. */ queryKey: QueryKey - /** - * The state of the query, including its data and when it was last updated. - */ + /** The state of the query, including its data and when it was last updated. */ state: QueryState } -/** - * A value, or a promise that resolves to it. - */ +/** A value, or a promise that resolves to it. */ export type MaybePromise = T | Promise /** - * A key-value storage, such as `localStorage` or `AsyncStorage`, whose methods may be synchronous - * or return promises. + * A key-value storage, such as `localStorage` or `AsyncStorage`, whose methods + * may be synchronous or return promises. */ export interface AsyncStorage { - /** - * Reads the value stored under `key`, or `null`/`undefined` if there is none. - */ + /** Reads the value stored under `key`, or `null`/`undefined` if there is none. */ getItem: (key: string) => MaybePromise - /** - * Stores `value` under `key`. - */ + /** Stores `value` under `key`. */ setItem: (key: string, value: TStorageValue) => MaybePromise - /** - * Removes the value stored under `key`. - */ + /** Removes the value stored under `key`. */ removeItem: (key: string) => MaybePromise /** - * Returns all stored key-value pairs. Required for removing expired entries in bulk. + * Returns all stored key-value pairs. Required for removing expired entries + * in bulk. */ entries?: () => MaybePromise> } -/** - * Options for {@link experimental_createQueryPersister}. - */ +/** Options for {@link experimental_createQueryPersister}. */ export interface StoragePersisterOptions { /** - * The storage client used for setting and retrieving items from cache. - * For SSR pass in `undefined`. + * The storage client used for setting and retrieving items from cache. For + * SSR pass in `undefined`. */ storage: AsyncStorage | undefined | null /** * How to serialize the data to storage. + * * @default `JSON.stringify` */ serialize?: (persistedQuery: PersistedQuery) => MaybePromise /** * How to deserialize the data from storage. + * * @default `JSON.parse` */ deserialize?: (cachedString: TStorageValue) => MaybePromise @@ -88,51 +74,52 @@ export interface StoragePersisterOptions { */ buster?: string /** - * The max-allowed age of the cache in milliseconds. - * If a persisted cache is found that is older than this - * time, it will be discarded + * The max-allowed age of the cache in milliseconds. If a persisted cache is + * found that is older than this time, it will be discarded + * * @default 24 hours */ maxAge?: number /** - * Prefix to be used for storage key. - * Storage key is a combination of prefix and query hash in a form of `prefix-queryHash`. + * Prefix to be used for storage key. Storage key is a combination of prefix + * and query hash in a form of `prefix-queryHash`. + * * @default 'tanstack-query' */ prefix?: string /** - * If set to `true`, the query will refetch on successful query restoration if the data is stale. - * If set to `false`, the query will not refetch on successful query restoration. - * If set to `'always'`, the query will always refetch on successful query restoration. + * If set to `true`, the query will refetch on successful query restoration if + * the data is stale. If set to `false`, the query will not refetch on + * successful query restoration. If set to `'always'`, the query will always + * refetch on successful query restoration. + * * @defaultValue true */ refetchOnRestore?: boolean | 'always' - /** - * Filters to narrow down which Queries should be persisted. - */ + /** Filters to narrow down which Queries should be persisted. */ filters?: QueryFilters } export const PERSISTER_KEY_PREFIX = 'tanstack-query' /** - * Warning: experimental feature. - * This utility function enables fine-grained query persistence. - * Simple add it as a `persister` parameter to `useQuery` or `defaultOptions` on `queryClient`. + * Warning: experimental feature. This utility function enables fine-grained + * query persistence. Simple add it as a `persister` parameter to `useQuery` or + * `defaultOptions` on `queryClient`. + * + * useQuery({ + * queryKey: ['myKey'], + * queryFn: fetcher, + * persister: createPersister({ + * storage: localStorage, + * }), + * }) * - * ``` - * useQuery({ - * queryKey: ['myKey'], - * queryFn: fetcher, - * persister: createPersister({ - * storage: localStorage, - * }), - * }) - * ``` - * @param options - The storage to persist to, and the options for serializing, expiring, and - * filtering persisted queries. - * @returns The `persisterFn` to pass as a query's `persister`, plus functions to persist, retrieve, - * restore, remove, and garbage collect persisted queries manually. + * @param options - The storage to persist to, and the options for serializing, + * expiring, and filtering persisted queries. + * @returns The `persisterFn` to pass as a query's `persister`, plus functions + * to persist, retrieve, restore, remove, and garbage collect persisted + * queries manually. */ export function experimental_createQueryPersister({ storage, @@ -150,9 +137,10 @@ export function experimental_createQueryPersister({ }: StoragePersisterOptions) { /** * Checks whether a persisted query should be discarded. + * * @param persistedQuery - The persisted query to check. - * @returns `true` if it has no `dataUpdatedAt`, is older than `maxAge`, or has a different - * `buster`. + * @returns `true` if it has no `dataUpdatedAt`, is older than `maxAge`, or + * has a different `buster`. */ function isExpiredOrBusted(persistedQuery: PersistedQuery) { if (persistedQuery.state.dataUpdatedAt) { @@ -171,12 +159,14 @@ export function experimental_createQueryPersister({ } /** - * Reads the persisted data of a query from storage. Expired, busted, or unreadable entries are - * removed instead. + * Reads the persisted data of a query from storage. Expired, busted, or + * unreadable entries are removed instead. + * * @param queryHash - The hash of the query to read. - * @param afterRestoreMacroTask - Scheduled with the persisted query after it is restored. - * @returns A promise that resolves with the persisted data, or `undefined` if nothing was - * restored. + * @param afterRestoreMacroTask - Scheduled with the persisted query after it + * is restored. + * @returns A promise that resolves with the persisted data, or `undefined` if + * nothing was restored. */ async function retrieveQuery( queryHash: string, @@ -224,6 +214,7 @@ export function experimental_createQueryPersister({ /** * Persists the query with the given key, if it exists in the client's cache. + * * @param queryKey - The key of the query to persist. * @param queryClient - The client whose cache holds the query. * @returns A promise that resolves once the query is persisted. @@ -249,6 +240,7 @@ export function experimental_createQueryPersister({ /** * Writes a query's state, key, hash, and `buster` to storage. + * * @param query - The query to persist. * @returns A promise that resolves once the entry is serialized and written. */ @@ -268,8 +260,9 @@ export function experimental_createQueryPersister({ } /** - * The `persister` of a query: restores its data from storage if the query has none yet, otherwise - * runs `queryFn` and persists the result. + * The `persister` of a query: restores its data from storage if the query has + * none yet, otherwise runs `queryFn` and persists the result. + * * @param queryFn - The query's own query function. * @param ctx - The context passed to `queryFn`. * @param query - The query being fetched. @@ -321,8 +314,9 @@ export function experimental_createQueryPersister({ } /** - * Removes expired, busted, or unreadable entries from storage. Requires the storage to implement - * `entries`. + * Removes expired, busted, or unreadable entries from storage. Requires the + * storage to implement `entries`. + * * @returns A promise that resolves once every entry is checked. */ async function persisterGc() { @@ -351,11 +345,13 @@ export function experimental_createQueryPersister({ } /** - * Restores every persisted query matching `filters` into the client's cache with - * `queryClient.setQueryData`. Requires the storage to implement `entries`. + * Restores every persisted query matching `filters` into the client's cache + * with `queryClient.setQueryData`. Requires the storage to implement + * `entries`. + * * @param queryClient - The client to restore the queries into. - * @param filters - The `queryKey` and `exact` filters to match. Without them, every query is - * restored. + * @param filters - The `queryKey` and `exact` filters to match. Without them, + * every query is restored. * @returns A promise that resolves once every entry is checked. */ async function restoreQueries( @@ -408,10 +404,11 @@ export function experimental_createQueryPersister({ } /** - * Removes every persisted query matching `filters` from storage. Requires the storage to implement - * `entries`. - * @param filters - The `queryKey` and `exact` filters to match. Without them, every query is - * removed. + * Removes every persisted query matching `filters` from storage. Requires the + * storage to implement `entries`. + * + * @param filters - The `queryKey` and `exact` filters to match. Without them, + * every query is removed. * @returns A promise that resolves once every entry is checked. */ async function removeQueries( diff --git a/packages/query-persist-client-core/src/persist.ts b/packages/query-persist-client-core/src/persist.ts index 22556505259..93603a8ecd3 100644 --- a/packages/query-persist-client-core/src/persist.ts +++ b/packages/query-persist-client-core/src/persist.ts @@ -7,91 +7,80 @@ import type { QueryClient, } from '@tanstack/query-core' -/** - * A value, or a promise-like that resolves to it. - */ +/** A value, or a promise-like that resolves to it. */ export type Promisable = T | PromiseLike -/** - * Saves, restores, and removes a {@link PersistedClient} in a storage. - */ +/** Saves, restores, and removes a {@link PersistedClient} in a storage. */ export interface Persister { - /** - * Saves the persisted client to the storage. - */ + /** Saves the persisted client to the storage. */ persistClient: (persistClient: PersistedClient) => Promisable /** - * Reads the persisted client from the storage, or `undefined` if nothing was saved. + * Reads the persisted client from the storage, or `undefined` if nothing was + * saved. */ restoreClient: () => Promisable - /** - * Removes the persisted client from the storage. - */ + /** Removes the persisted client from the storage. */ removeClient: () => Promisable } /** - * The dehydrated state of a `QueryClient` as it is persisted, with the time it was saved and its - * `buster`. + * The dehydrated state of a `QueryClient` as it is persisted, with the time it + * was saved and its `buster`. */ export interface PersistedClient { /** - * When the client was saved, in milliseconds since the epoch. Compared with `maxAge` on restore. + * When the client was saved, in milliseconds since the epoch. Compared with + * `maxAge` on restore. */ timestamp: number /** - * The `buster` the client was saved with. A persisted client with a different `buster` is - * discarded. + * The `buster` the client was saved with. A persisted client with a different + * `buster` is discarded. */ buster: string - /** - * The dehydrated cache of the `QueryClient`. - */ + /** The dehydrated cache of the `QueryClient`. */ clientState: DehydratedState } -/** - * The options shared by restoring and saving a persisted `QueryClient`. - */ +/** The options shared by restoring and saving a persisted `QueryClient`. */ export interface PersistQueryClientRootOptions { /** The QueryClient to persist */ queryClient: QueryClient /** - * The Persister interface for storing and restoring the cache - * to/from a persisted location + * The Persister interface for storing and restoring the cache to/from a + * persisted location */ persister: Persister /** - * A unique string that can be used to forcefully - * invalidate existing caches if they do not share the same buster string + * A unique string that can be used to forcefully invalidate existing caches + * if they do not share the same buster string */ buster?: string } /** - * Options for restoring a persisted `QueryClient` with {@link persistQueryClientRestore}. + * Options for restoring a persisted `QueryClient` with + * {@link persistQueryClientRestore}. */ export interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions { /** - * The max-allowed age of the cache in milliseconds. - * If a persisted cache is found that is older than this - * time, it will be discarded + * The max-allowed age of the cache in milliseconds. If a persisted cache is + * found that is older than this time, it will be discarded */ maxAge?: number /** The options passed to the hydrate function */ hydrateOptions?: HydrateOptions } -/** - * Options for saving a `QueryClient` with {@link persistQueryClientSave}. - */ +/** Options for saving a `QueryClient` with {@link persistQueryClientSave}. */ export interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions { /** The options passed to the dehydrate function */ dehydrateOptions?: DehydrateOptions } /** - * Options for {@link persistQueryClient}, which both restores and saves a `QueryClient`. + * Options for {@link persistQueryClient}, which both restores and saves a + * `QueryClient`. */ export interface PersistQueryClientOptions extends @@ -102,8 +91,9 @@ export interface PersistQueryClientOptions const cacheEventTypes: Array = ['added', 'removed', 'updated'] /** - * Checks if emitted event is about cache change and not about observers. - * Useful for persist, where we only want to trigger save when cache is changed. + * Checks if emitted event is about cache change and not about observers. Useful + * for persist, where we only want to trigger save when cache is changed. + * * @param eventType - The type of the emitted event. * @returns `true` if the event is `'added'`, `'removed'`, or `'updated'`. */ @@ -113,14 +103,18 @@ function isCacheEventType(eventType: NotifyEventType) { /** * Restores persisted data to the QueryCache. - * - data obtained from persister.restoreClient. - * - data is hydrated using hydrateOptions. - * If data is expired, busted, empty, or throws, it runs persister.removeClient. - * @param options - The `queryClient` to restore into, the `persister`, and the `maxAge`, `buster`, - * and `hydrateOptions` that decide whether and how the persisted data is restored. - * @returns A promise that resolves once the data is restored or removed. If restoring throws, it - * attempts to remove the persisted data and then rejects with the restore error, or with the removal - * error if the removal fails too. + * + * - Data obtained from persister.restoreClient. + * - Data is hydrated using hydrateOptions. If data is expired, busted, empty, or + * throws, it runs persister.removeClient. + * + * @param options - The `queryClient` to restore into, the `persister`, and the + * `maxAge`, `buster`, and `hydrateOptions` that decide whether and how the + * persisted data is restored. + * @returns A promise that resolves once the data is restored or removed. If + * restoring throws, it attempts to remove the persisted data and then rejects + * with the restore error, or with the removal error if the removal fails + * too. */ export async function persistQueryClientRestore({ queryClient, @@ -161,10 +155,12 @@ export async function persistQueryClientRestore({ /** * Persists data from the QueryCache. - * - data dehydrated using dehydrateOptions. - * - data is persisted using persister.persistClient. - * @param options - The `queryClient` to persist, the `persister`, the `buster`, and the - * `dehydrateOptions`. + * + * - Data dehydrated using dehydrateOptions. + * - Data is persisted using persister.persistClient. + * + * @param options - The `queryClient` to persist, the `persister`, the `buster`, + * and the `dehydrateOptions`. */ export async function persistQueryClientSave({ queryClient, @@ -183,9 +179,10 @@ export async function persistQueryClientSave({ /** * Subscribe to QueryCache and MutationCache updates (for persisting). - * @param props - The `queryClient` to monitor, the `persister`, the `buster`, and the - * `dehydrateOptions` used for each save. - * @returns an unsubscribe function (to discontinue monitoring) + * + * @param props - The `queryClient` to monitor, the `persister`, the `buster`, + * and the `dehydrateOptions` used for each save. + * @returns An unsubscribe function (to discontinue monitoring) */ export function persistQueryClientSubscribe( props: PersistedQueryClientSaveOptions, @@ -214,9 +211,10 @@ export function persistQueryClientSubscribe( /** * Restores persisted data to QueryCache and persists further changes. + * * @param props - The options for both restoring and saving. - * @returns A tuple of a function that stops persisting, and a promise that resolves once the - * restore is done. + * @returns A tuple of a function that stops persisting, and a promise that + * resolves once the restore is done. */ export function persistQueryClient( props: PersistQueryClientOptions, diff --git a/packages/query-persist-client-core/src/retryStrategies.ts b/packages/query-persist-client-core/src/retryStrategies.ts index b20c81be4b3..b953f6480d6 100644 --- a/packages/query-persist-client-core/src/retryStrategies.ts +++ b/packages/query-persist-client-core/src/retryStrategies.ts @@ -1,8 +1,8 @@ import type { PersistedClient } from './persist' /** - * Called when saving the persisted client fails. Returns a smaller client to try saving again, or - * `undefined` to give up. + * Called when saving the persisted client fails. Returns a smaller client to + * try saving again, or `undefined` to give up. */ export type PersistRetryer = (props: { persistedClient: PersistedClient @@ -11,10 +11,12 @@ export type PersistRetryer = (props: { }) => PersistedClient | undefined /** - * A {@link PersistRetryer} that drops the query with the oldest `dataUpdatedAt` and tries again, until - * no queries are left. + * A {@link PersistRetryer} that drops the query with the oldest `dataUpdatedAt` + * and tries again, until no queries are left. + * * @param props - The `persistedClient` that failed to save. - * @returns A copy of the client without its oldest query, or `undefined` if it has no queries. + * @returns A copy of the client without its oldest query, or `undefined` if it + * has no queries. */ export const removeOldestQuery: PersistRetryer = ({ persistedClient }) => { const mutations = [...persistedClient.clientState.mutations] diff --git a/packages/query-sync-storage-persister/src/index.ts b/packages/query-sync-storage-persister/src/index.ts index de2f9d4261e..0a09fbb3db5 100644 --- a/packages/query-sync-storage-persister/src/index.ts +++ b/packages/query-sync-storage-persister/src/index.ts @@ -15,25 +15,24 @@ interface Storage { interface CreateSyncStoragePersisterOptions { /** - * The storage client used for setting and retrieving items from cache. - * For SSR pass in `undefined`. Note that window.localStorage can be - * `null` in Android WebViews depending on how they are configured. + * The storage client used for setting and retrieving items from cache. For + * SSR pass in `undefined`. Note that window.localStorage can be `null` in + * Android WebViews depending on how they are configured. */ storage: Storage | undefined | null /** The key to use when storing the cache */ key?: string - /** - * To avoid spamming, - * pass a time in ms to throttle saving the cache to disk - */ + /** To avoid spamming, pass a time in ms to throttle saving the cache to disk */ throttleTime?: number /** * How to serialize the data to storage. + * * @default `JSON.stringify` */ serialize?: (client: PersistedClient) => string /** * How to deserialize the data from storage. + * * @default `JSON.parse` */ deserialize?: (cachedString: string) => PersistedClient @@ -44,11 +43,13 @@ interface CreateSyncStoragePersisterOptions { /** * Creates a persister that stores the client in a synchronous storage such as * `window.localStorage`. - * @param options - The `storage` to persist to, the `key`, `throttleTime`, `serialize`, - * `deserialize`, and `retry` options. - * @returns A persister that saves, restores, and removes the client in `storage`. Without - * `storage`, its methods do nothing. - * @deprecated use `createAsyncStoragePersister` from `@tanstack/query-async-storage-persister` instead. + * + * @deprecated use `createAsyncStoragePersister` from + * `@tanstack/query-async-storage-persister` instead. + * @param options - The `storage` to persist to, the `key`, `throttleTime`, + * `serialize`, `deserialize`, and `retry` options. + * @returns A persister that saves, restores, and removes the client in + * `storage`. Without `storage`, its methods do nothing. */ export function createSyncStoragePersister({ storage, @@ -108,8 +109,9 @@ export function createSyncStoragePersister({ } /** - * Wraps a function so it runs at most once per `wait` milliseconds, with the arguments of the latest - * call. + * Wraps a function so it runs at most once per `wait` milliseconds, with the + * arguments of the latest call. + * * @param func - The function to throttle. * @param wait - The time to wait before running `func`, in milliseconds. * @returns The throttled function. diff --git a/packages/query-sync-storage-persister/src/utils.ts b/packages/query-sync-storage-persister/src/utils.ts index 988c820d6ab..4ce7a74cd2c 100644 --- a/packages/query-sync-storage-persister/src/utils.ts +++ b/packages/query-sync-storage-persister/src/utils.ts @@ -1,6 +1,4 @@ -/** - * A function that does nothing. - */ +/** A function that does nothing. */ export function noop(): void export function noop(): undefined export function noop() {} diff --git a/packages/query-test-utils/src/mockVisibilityState.ts b/packages/query-test-utils/src/mockVisibilityState.ts index 1b8596db431..109c73e6b8e 100644 --- a/packages/query-test-utils/src/mockVisibilityState.ts +++ b/packages/query-test-utils/src/mockVisibilityState.ts @@ -3,6 +3,7 @@ import type { MockInstance } from 'vitest' /** * Mocks `document.visibilityState` to return a given value. + * * @param value - The visibility state to return. * @returns The spy, to restore the original getter with `mockRestore()`. */ diff --git a/packages/query-test-utils/src/queryKey.ts b/packages/query-test-utils/src/queryKey.ts index 10b6bf0c1b1..ceff2eb4d46 100644 --- a/packages/query-test-utils/src/queryKey.ts +++ b/packages/query-test-utils/src/queryKey.ts @@ -1,7 +1,9 @@ let queryKeyCount = 0 /** - * Creates a query key that no other call returns, so tests don't share cache entries. + * Creates a query key that no other call returns, so tests don't share cache + * entries. + * * @returns A new key like `['query_1']`. */ export const queryKey = (): Array => { diff --git a/packages/query-test-utils/src/sleep.ts b/packages/query-test-utils/src/sleep.ts index 3929e6956ba..accfdc6de7a 100644 --- a/packages/query-test-utils/src/sleep.ts +++ b/packages/query-test-utils/src/sleep.ts @@ -1,5 +1,7 @@ /** - * Waits for a number of milliseconds, e.g. to delay a `queryFn` under fake timers. + * Waits for a number of milliseconds, e.g. to delay a `queryFn` under fake + * timers. + * * @param ms - How long to wait, in milliseconds. * @returns A promise that resolves after `ms` milliseconds. */ diff --git a/packages/react-query-devtools/src/ReactQueryDevtools.tsx b/packages/react-query-devtools/src/ReactQueryDevtools.tsx index 9f13c8c82f5..277ae26e573 100644 --- a/packages/react-query-devtools/src/ReactQueryDevtools.tsx +++ b/packages/react-query-devtools/src/ReactQueryDevtools.tsx @@ -11,57 +11,57 @@ import type { import type { QueryClient } from '@tanstack/react-query' /** - * The props of `ReactQueryDevtools`, which renders the devtools with a toggle button that opens - * them. + * The props of `ReactQueryDevtools`, which renders the devtools with a toggle + * button that opens them. */ export interface DevtoolsOptions { - /** - * Set this true if you want the dev tools to default to being open - */ + /** Set this true if you want the dev tools to default to being open */ initialIsOpen?: boolean /** * The position of the TanStack logo to open and close the devtools panel. * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'relative' + * * @defaultValue bottom-right */ buttonPosition?: DevtoolsButtonPosition /** - * The position of the React Query devtools panel. - * 'top' | 'bottom' | 'left' | 'right' + * The position of the React Query devtools panel. 'top' | 'bottom' | 'left' | + * 'right' + * * @defaultValue bottom */ position?: DevtoolsPosition - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Set this to true to hide disabled queries from the devtools panel. - */ + /** Set this to true to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Set this to 'light', 'dark', or 'system' to change the theme of the + * devtools panel. + * * @defaultValue system */ theme?: Theme } /** - * Renders the TanStack Query devtools, with a toggle button that opens them, for the given or - * nearest `QueryClient`. + * Renders the TanStack Query devtools, with a toggle button that opens them, + * for the given or nearest `QueryClient`. + * * @param props - The devtools options. * @returns The element the devtools are mounted in. */ diff --git a/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx b/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx index a9eda49e7d8..42ca3ff1db3 100644 --- a/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx +++ b/packages/react-query-devtools/src/ReactQueryDevtoolsPanel.tsx @@ -6,52 +6,57 @@ import type { DevtoolsErrorType, Theme } from '@tanstack/query-devtools' import type { QueryClient } from '@tanstack/react-query' /** - * The props of `ReactQueryDevtoolsPanel`, which renders the devtools panel inline. + * The props of `ReactQueryDevtoolsPanel`, which renders the devtools panel + * inline. */ export interface DevtoolsPanelOptions { - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot /** * Custom styles for the devtools panel + * + * @example + * ;({ height: '100%' }) + * + * @example + * ;({ height: '100%', width: '100%' }) + * * @default { height: '500px' } - * @example { height: '100%' } - * @example { height: '100%', width: '100%' } */ style?: React.CSSProperties - /** - * Callback function that is called when the devtools panel is closed - */ + /** Callback function that is called when the devtools panel is closed */ onClose?: () => void - /** - * Set this to true to hide disabled queries from the devtools panel. - */ + /** Set this to true to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Set this to 'light', 'dark', or 'system' to change the theme of the + * devtools panel. + * * @defaultValue system */ theme?: Theme } /** - * Renders the TanStack Query devtools panel inline, for the given or nearest `QueryClient`. + * Renders the TanStack Query devtools panel inline, for the given or nearest + * `QueryClient`. + * * @param props - The devtools panel options. * @returns The element the devtools panel is mounted in. */ diff --git a/packages/react-query-devtools/src/index.ts b/packages/react-query-devtools/src/index.ts index 23053dac759..557a54c32d9 100644 --- a/packages/react-query-devtools/src/index.ts +++ b/packages/react-query-devtools/src/index.ts @@ -18,6 +18,7 @@ export const ReactQueryDevtoolsPanel: (typeof DevtoolsPanel)['ReactQueryDevtools : DevtoolsPanel.ReactQueryDevtoolsPanel /** - * The props of `ReactQueryDevtoolsPanel`, which renders the devtools panel inline. + * The props of `ReactQueryDevtoolsPanel`, which renders the devtools panel + * inline. */ export type DevtoolsPanelOptions = DevtoolsPanel.DevtoolsPanelOptions diff --git a/packages/react-query-next-experimental/src/HydrationStreamProvider.tsx b/packages/react-query-next-experimental/src/HydrationStreamProvider.tsx index 56bd4ea557f..6f12d7e77b9 100644 --- a/packages/react-query-next-experimental/src/HydrationStreamProvider.tsx +++ b/packages/react-query-next-experimental/src/HydrationStreamProvider.tsx @@ -25,46 +25,38 @@ interface HydrationStreamContext { id: string stream: { /** - * **Server method** - * Push a new entry to the stream - * Will be ignored on the client + * **Server method** Push a new entry to the stream Will be ignored on the + * client */ push: (...shape: Array) => void } } -/** - * The props of the `Provider` returned by `createHydrationStreamProvider`. - */ +/** The props of the `Provider` returned by `createHydrationStreamProvider`. */ export interface HydrationStreamProviderProps { - /** - * The children to render inside the stream provider. - */ + /** The children to render inside the stream provider. */ children: React.ReactNode /** - * Optional transformer to serialize/deserialize the data - * Example devalue, superjson et al + * Optional transformer to serialize/deserialize the data Example devalue, + * superjson et al */ transformer?: DataTransformer - /** - * **Client method** - * Called in the browser when new entries are received - */ + /** **Client method** Called in the browser when new entries are received */ onEntries: (entries: Array) => void - /** - * **Server method** - * onFlush is called on the server when the cache is flushed - */ + /** **Server method** onFlush is called on the server when the cache is flushed */ onFlush?: () => Array /** - * A nonce that'll allow the inline script to be executed when Content Security Policy is enforced + * A nonce that'll allow the inline script to be executed when Content + * Security Policy is enforced */ nonce?: string } /** - * Creates a provider that streams entries (e.g. dehydrated query state) from the server to the - * client while the page streams in, and the context it shares the stream through. + * Creates a provider that streams entries (e.g. dehydrated query state) from + * the server to the client while the page streams in, and the context it shares + * the stream through. + * * @returns The `Provider` component and its `context`. */ export function createHydrationStreamProvider() { @@ -72,36 +64,42 @@ export function createHydrationStreamProvider() { null as any, ) /** - * 1. (Happens on server): the callback registered with `useServerInsertedHTML()` is called **on the server** whenever - * Next.js inserts HTML into the streamed response. - * - This means that we might have some new entries in the cache that needs to be flushed. - * - We pass these to the client by inserting a ` + * * - * + * * ... - * - * ``` + * + * ``` + * + * @param client - The `QueryClient` to make available to descendant components. */ export const setQueryClientContext = (client: QueryClient): void => { setContext(_contextKey, client) @@ -47,8 +53,9 @@ const _isRestoringContextKey = Symbol('isRestoring') /** * Retrieves a `isRestoring` from Svelte's context. - * @returns The `isRestoring` box set on context, or a box holding `false` if none was set or the - * context is unavailable. + * + * @returns The `isRestoring` box set on context, or a box holding `false` if + * none was set or the context is unavailable. */ export const getIsRestoringContext = (): Box => { try { @@ -63,7 +70,9 @@ export const getIsRestoringContext = (): Box => { /** * Sets a `isRestoring` on Svelte's context. - * @param isRestoring - The box holding whether the cache is being restored, e.g. by a persister. + * + * @param isRestoring - The box holding whether the cache is being restored, + * e.g. by a persister. */ export const setIsRestoringContext = (isRestoring: Box): void => { setContext(_isRestoringContextKey, isRestoring) diff --git a/packages/svelte-query/src/createBaseQuery.svelte.ts b/packages/svelte-query/src/createBaseQuery.svelte.ts index 5c3f69ab60f..24aca6be407 100644 --- a/packages/svelte-query/src/createBaseQuery.svelte.ts +++ b/packages/svelte-query/src/createBaseQuery.svelte.ts @@ -12,6 +12,7 @@ import type { /** * Base implementation for `createQuery` and `createInfiniteQuery` + * * @param options - A function that returns query options * @param Observer - The observer from query-core * @param queryClient - Custom query client which overrides provider @@ -63,8 +64,9 @@ export function createBaseQuery< ) /** - * Computes the observer's current result for the resolved options, tracking property access unless - * `notifyOnChangeProps` is set. + * Computes the observer's current result for the resolved options, tracking + * property access unless `notifyOnChangeProps` is set. + * * @returns The current query result. */ function createResult() { diff --git a/packages/svelte-query/src/createInfiniteQuery.ts b/packages/svelte-query/src/createInfiniteQuery.ts index bba0b4aa40c..b9f941af439 100644 --- a/packages/svelte-query/src/createInfiniteQuery.ts +++ b/packages/svelte-query/src/createInfiniteQuery.ts @@ -19,16 +19,20 @@ import type { } from './infiniteQueryOptions.js' /** - * The options for `createInfiniteQuery` are identical to `createQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. + * The options for `createInfiniteQuery` are identical to `createQuery`, with + * the addition of `initialPageParam`, `getNextPageParam`, + * `getPreviousPageParam`, and `maxPages`. * * This overload is selected when `initialData` is known to be defined. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `createInfiniteQuery`, with `initialData` set, wrapped in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result, plus `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` - * to page through the query. + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `createInfiniteQuery`, with `initialData` set, + * wrapped in an {@link Accessor} so options can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result, plus + * `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` to page + * through the query. * @see {@link infiniteQueryOptions} to share these options between `createInfiniteQuery` and imperative APIs * like `queryClient.infiniteQuery`. */ @@ -52,16 +56,21 @@ export function createInfiniteQuery< ): DefinedCreateInfiniteQueryResult /** - * The options for `createInfiniteQuery` are identical to `createQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. + * The options for `createInfiniteQuery` are identical to `createQuery`, with + * the addition of `initialPageParam`, `getNextPageParam`, + * `getPreviousPageParam`, and `maxPages`. + * + * This overload is selected when `initialData` is omitted or may be + * `undefined`. * - * This overload is selected when `initialData` is omitted or may be `undefined`. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `createInfiniteQuery`, wrapped in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result, plus `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` - * to page through the query. + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `createInfiniteQuery`, wrapped in an + * {@link Accessor} so options can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result, plus + * `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` to page + * through the query. * @see {@link infiniteQueryOptions} to share these options between `createInfiniteQuery` and imperative APIs * like `queryClient.infiniteQuery`. */ @@ -85,97 +94,103 @@ export function createInfiniteQuery< ): CreateInfiniteQueryResult /** - * The options for `createInfiniteQuery` are identical to `createQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. - * @param options - The {@link CreateInfiniteQueryOptions} to use — everything you can pass to - * `createInfiniteQuery`, wrapped in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result, plus `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` - * to page through the query. - * @see {@link infiniteQueryOptions} to share these options between `createInfiniteQuery` and imperative APIs - * like `queryClient.infiniteQuery`. + * The options for `createInfiniteQuery` are identical to `createQuery`, with + * the addition of `initialPageParam`, `getNextPageParam`, + * `getPreviousPageParam`, and `maxPages`. + * * @example - * Fetching the next page from a "Load More" button click: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *
    - * {#each query.data.pages as page} - * {#each page.projects as project (project.id)} - *
  • {project.name}
  • - * {/each} - * {/each} + * {#each query.data.pages as page} + * {#each page.projects as project (project.id)} + *
  • {project.name}
  • + * {/each} + * {/each} *
* - * {/if} - * ``` + * {/if} + * ``` + * * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a - * sentinel element after the list: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *
    - * {#each query.data.pages as page} - * {#each page.projects as project (project.id)} - *
  • {project.name}
  • - * {/each} - * {/each} + * {#each query.data.pages as page} + * {#each page.projects as project (project.id)} + *
  • {project.name}
  • + * {/each} + * {/each} *
*
- * {/if} - * ``` + * {/if} + * ``` + * + * @param options - The {@link CreateInfiniteQueryOptions} to use — everything + * you can pass to `createInfiniteQuery`, wrapped in an {@link Accessor} so + * options can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result, plus + * `fetchNextPage`/`fetchPreviousPage`/`hasNextPage`/`hasPreviousPage` to page + * through the query. + * @see {@link infiniteQueryOptions} to share these options between `createInfiniteQuery` and imperative APIs + * like `queryClient.infiniteQuery`. */ export function createInfiniteQuery< TQueryFnData, diff --git a/packages/svelte-query/src/createMutation.svelte.ts b/packages/svelte-query/src/createMutation.svelte.ts index 073aa69166c..98e596be16d 100644 --- a/packages/svelte-query/src/createMutation.svelte.ts +++ b/packages/svelte-query/src/createMutation.svelte.ts @@ -11,156 +11,163 @@ import type { import type { DefaultError, QueryClient } from '@tanstack/query-core' /** - * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. - * `createMutation` is the function for that. - * @param options - The {@link CreateMutationOptions} to use, wrapped in an {@link Accessor} so options can be - * reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second - * argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared - * mutation definition. If you make multiple requests, `onSuccess` will fire only after the latest call you've - * made. - * @see {@link mutationOptions} to share these options across multiple `createMutation` call sites, or to look - * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). + * Unlike queries, mutations are typically used to create/update/delete data or + * perform server side-effects. `createMutation` is the function for that. + * * @example - * ```svelte - * + * * - * - * ``` + * + * ``` + * * @example - * Rendering the mutation's own state, rather than just firing it off: - * ```svelte - * + * * - * {#if addMutation.isPending} + * {#if addMutation.isPending} * Adding todo... - * {:else} + * {:else} * {#if addMutation.isError} - *
An error occurred: {addMutation.error.message}
+ *
An error occurred: {addMutation.error.message}
* {/if} * - * {/if} - * ``` + * {/if} + * ``` + * * @example - * Optimistic update via `onMutate`, rolling back on `onError`: - * ```svelte - * + * + * + * + * ``` * - * - * ``` * @example - * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a - * promise per call instead, so you can wait for all of them when they succeed: - * ```svelte - * + * * - * - * ``` + * + * ``` + * * @example - * If some of the mutations above can fail independently of the others, and you want to know which ones - * did — rather than losing that information the moment the first one rejects — swap `Promise.all` for - * `Promise.allSettled`: - * ```svelte - * + * }) + * } + * * - * - * ``` + * + * ``` + * + * @param options - The {@link CreateMutationOptions} to use, wrapped in an + * {@link Accessor} so options can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns `mutate`/`mutateAsync` also accept per-call + * `onSuccess`/`onError`/`onSettled` callbacks as a second argument, useful + * for triggering call-site side effects (e.g. navigation) without coupling + * them to the shared mutation definition. If you make multiple requests, + * `onSuccess` will fire only after the latest call you've made. + * @see {@link mutationOptions} to share these options across multiple `createMutation` call sites, or to look + * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). */ export function createMutation< TData = unknown, diff --git a/packages/svelte-query/src/createQueries.svelte.ts b/packages/svelte-query/src/createQueries.svelte.ts index 96492535463..085982a4715 100644 --- a/packages/svelte-query/src/createQueries.svelte.ts +++ b/packages/svelte-query/src/createQueries.svelte.ts @@ -124,7 +124,8 @@ type GetCreateQueryResult = CreateQueryResult /** - * QueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + * QueriesOptions reducer recursively unwraps function arguments to + * infer/enforce type param */ export type QueriesOptions< T extends Array, @@ -165,9 +166,7 @@ export type QueriesOptions< : // Fallback Array -/** - * QueriesResults reducer recursively maps type param to results - */ +/** QueriesResults reducer recursively maps type param to results */ export type QueriesResults< T extends Array, TResults extends Array = [], @@ -187,74 +186,79 @@ export type QueriesResults< : { [K in keyof T]: GetCreateQueryResult } /** - * The `createQueries` function can be used to fetch a variable number of queries. - * @param createQueriesOptions - The `queries` array to run, and an optional `combine` function, wrapped in an - * {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context - * will be used. - * @returns An array with one result per query, in the same order as `queries` — or, if `combine` is provided, - * whatever `combine` returns. + * The `createQueries` function can be used to fetch a variable number of + * queries. + * * @example - * ```svelte - * + * * - *
    + *
      * {#each postQueries as query, index (ids[index])} - * {#if query.isPending} - *
    • Loading...
    • - * {:else if query.isError} - *
    • Error: {query.error.message}
    • - * {:else} - *
    • {query.data.title}
    • - * {/if} + * {#if query.isPending} + *
    • Loading...
    • + * {:else if query.isError} + *
    • Error: {query.error.message}
    • + * {:else} + *
    • {query.data.title}
    • + * {/if} * {/each} - *
    - * ``` + *
+ * ``` + * * @example - * Combining results into a single value: - * ```svelte - * + * * - * {#if combined.isPending} + * {#if combined.isPending} * Loading... - * {:else if combined.isError} + * {:else if combined.isError} * Error loading posts - * {:else} + * {:else} *
    - * {#each combined.data as post} - *
  • {post?.title}
  • - * {/each} + * {#each combined.data as post} + *
  • {post?.title}
  • + * {/each} *
- * {/if} - * ``` + * {/if} + * ``` + * + * @param createQueriesOptions - The `queries` array to run, and an optional + * `combine` function, wrapped in an {@link Accessor} so options can be + * reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns An array with one result per query, in the same order as `queries` — + * or, if `combine` is provided, whatever `combine` returns. */ export function createQueries< T extends Array, @@ -295,7 +299,9 @@ export function createQueries< ) /** - * Computes the combined result of the observer's queries for the resolved options. + * Computes the combined result of the observer's queries for the resolved + * options. + * * @returns The combined result, built from the tracked per-query results. */ function createResult() { diff --git a/packages/svelte-query/src/createQuery.ts b/packages/svelte-query/src/createQuery.ts index 9b9032d9da3..a64f69e8381 100644 --- a/packages/svelte-query/src/createQuery.ts +++ b/packages/svelte-query/src/createQuery.ts @@ -13,42 +13,49 @@ import type { } from './queryOptions.js' /** - * Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. - * The query runs when the options call for it — `enabled: false` skips the initial fetch. + * Subscribes to a query: a declarative dependency on an asynchronous source of + * data that is tied to a unique key. The query runs when the options call for + * it — `enabled: false` skips the initial fetch. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `createQuery`, - * with `initialData` set, wrapped in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result, typed so that `status` is `success` — or `error` if a fetch attempt - * fails while keeping the existing data (`status` never resolves to `pending` in this overload's type, - * since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. * @example - * ```svelte - * + * * - * {#if query.isError} + * {#if query.isError} * Error: {query.error.message} - * {/if} - *
    + * {/if} + *
      * {#each query.data as post (post.id)} - *
    • {post.title}
    • + *
    • {post.title}
    • * {/each} - *
    - * ``` + *
+ * ``` + * + * @param options - The {@link DefinedInitialDataOptions} to use — everything + * you can pass to `createQuery`, with `initialData` set, wrapped in an + * {@link Accessor} so options can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result, typed so that `status` is `success` — or + * `error` if a fetch attempt fails while keeping the existing data (`status` + * never resolves to `pending` in this overload's type, since `initialData` + * guarantees data upfront). `isSuccess`/`isError` are derived booleans for + * convenience. + * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. */ export function createQuery< TQueryFnData = unknown, @@ -63,63 +70,69 @@ export function createQuery< ): DefinedCreateQueryResult /** - * Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. - * The query runs when the options call for it — `enabled: false` skips the initial fetch. - * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `createQuery`, - * wrapped in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result. `status` is `pending` if there is no cached data to display, `error` if - * the last fetch attempt failed, or `success` if the query has data to display. `isPending`/`isSuccess`/`isError` - * are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. + * Subscribes to a query: a declarative dependency on an asynchronous source of + * data that is tied to a unique key. The query runs when the options call for + * it — `enabled: false` skips the initial fetch. + * * @example - * ```svelte - * + * * - * {#if query.status === 'pending'} + * {#if query.status === 'pending'} * Loading... - * {:else if query.status === 'error'} + * {:else if query.status === 'error'} * Error: {query.error.message} - * {:else} + * {:else} *
    - * {#each query.data as post (post.id)} - *
  • {post.title}
  • - * {/each} + * {#each query.data as post (post.id)} + *
  • {post.title}
  • + * {/each} *
- * {/if} - * ``` + * {/if} + * ``` + * * @example - * The same query, checking `isPending`/`isError` instead of `status` — pick whichever reads better to you: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *
    - * {#each query.data as post (post.id)} - *
  • {post.title}
  • - * {/each} + * {#each query.data as post (post.id)} + *
  • {post.title}
  • + * {/each} *
- * {/if} - * ``` + * {/if} + * ``` + * + * @param options - The {@link UndefinedInitialDataOptions} to use — everything + * you can pass to `createQuery`, wrapped in an {@link Accessor} so options + * can be reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result. `status` is `pending` if there is no + * cached data to display, `error` if the last fetch attempt failed, or + * `success` if the query has data to display. + * `isPending`/`isSuccess`/`isError` are derived booleans for convenience. + * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. */ export function createQuery< TQueryFnData = unknown, @@ -134,69 +147,65 @@ export function createQuery< ): CreateQueryResult /** - * Fallback overload for options whose `initialData` presence isn't statically known — for example, an - * object typed as {@link CreateQueryOptions} rather than an object literal. Prefer one of the other - * overloads when possible, since they infer whether `data` can be `undefined` from `initialData` directly. - * @param options - The {@link CreateQueryOptions} to use — everything you can pass to `createQuery`, wrapped - * in an {@link Accessor} so options can be reactive. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current query result. `status` is `pending` if there is no cached data to display, `error` if - * the last fetch attempt failed, or `success` if the query has data to display. `isPending`/`isSuccess`/`isError` - * are derived booleans for convenience. - * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. + * Fallback overload for options whose `initialData` presence isn't statically + * known — for example, an object typed as {@link CreateQueryOptions} rather than + * an object literal. Prefer one of the other overloads when possible, since + * they infer whether `data` can be `undefined` from `initialData` directly. + * * @example - * `select` derives whatever `data` a component needs from the cached value, without changing what's - * actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} * {query.data} posts - * {/if} - * ``` + * {/if} + * ``` + * * @example - * A dependent query, only enabled once `postId` is set — use `isLoading`, not `isPending`, so the - * loading state doesn't show while the query is disabled: - * ```svelte - * + * * - * {#if postId == null} + * {#if postId == null} * Select a post - * {:else if query.isLoading} + * {:else if query.isLoading} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *

{query.data?.title}

- * {/if} - * ``` + * {/if} + * ``` + * * @example - * Seeding a detail query from an already-cached list, to skip the loading state: - * ```svelte - * + * * - * {#if query.isError} + * {#if query.isError} * Error: {query.error.message} - * {/if} - *

{query.data?.title}

- * ``` + * {/if} + *

{query.data?.title}

+ * ``` + * * @example - * Paginated data, keeping the previous page's data visible while the next page loads: - * ```svelte - * + * * - * {#if query.isError} + * {#if query.isError} * Error: {query.error.message} - * {/if} - *
    + * {/if} + *
      * {#each query.data ?? [] as post (post.id)} - *
    • {post.title}
    • + *
    • {post.title}
    • * {/each} - *
    - *
+ * - * ``` + * + * ``` + * + * @param options - The {@link CreateQueryOptions} to use — everything you can + * pass to `createQuery`, wrapped in an {@link Accessor} so options can be + * reactive. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current query result. `status` is `pending` if there is no + * cached data to display, `error` if the last fetch attempt failed, or + * `success` if the query has data to display. + * `isPending`/`isSuccess`/`isError` are derived booleans for convenience. + * @see {@link queryOptions} to share these options between `createQuery` and imperative APIs like `queryClient.query`. */ export function createQuery< TQueryFnData, diff --git a/packages/svelte-query/src/infiniteQueryOptions.ts b/packages/svelte-query/src/infiniteQueryOptions.ts index 3bdf8e054f5..85d0ae40272 100644 --- a/packages/svelte-query/src/infiniteQueryOptions.ts +++ b/packages/svelte-query/src/infiniteQueryOptions.ts @@ -9,8 +9,9 @@ import type { import type { CreateInfiniteQueryOptions } from './types.js' /** - * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is omitted or may - * be `undefined` — `data` may be `undefined` while the query is `pending`. + * The options accepted by the `infiniteQueryOptions` overload selected when + * `initialData` is omitted or may be `undefined` — `data` may be `undefined` + * while the query is `pending`. */ export type UndefinedInitialDataInfiniteOptions< TQueryFnData = unknown, @@ -34,8 +35,9 @@ export type UndefinedInitialDataInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is known to be - * defined — `data` is never `undefined` (unless a `select` changes `TData` to include `undefined`). + * The options accepted by the `infiniteQueryOptions` overload selected when + * `initialData` is known to be defined — `data` is never `undefined` (unless a + * `select` changes `TData` to include `undefined`). */ export type DefinedInitialDataInfiniteOptions< TQueryFnData = unknown, @@ -56,44 +58,49 @@ export type DefinedInitialDataInfiniteOptions< } /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `createInfiniteQuery`. - * These options can be shared across `createInfiniteQuery` calls and imperative APIs such as - * `queryClient.infiniteQuery`. `options.queryKey` is required and is the query key to generate options for. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `createInfiniteQuery`. These options can be shared across + * `createInfiniteQuery` calls and imperative APIs such as + * `queryClient.infiniteQuery`. `options.queryKey` is required and is the query + * key to generate options for. * * This overload is selected when `initialData` is known to be defined. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `createInfiniteQuery`, with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link createInfiniteQuery} to run an infinite query with these options. + * * @example - * `initialData` skips the loading state on first render — even if a refetch fails, the list stays - * visible alongside the error: - * ```svelte - * + * * - * {#if query.isError} + * {#if query.isError} * Error: {query.error.message} - * {/if} - *
    + * {/if} + *
      * {#each query.data.pages as page} - * {#each page.projects as project (project.id)} - *
    • {project.name}
    • - * {/each} + * {#each page.projects as project (project.id)} + *
    • {project.name}
    • + * {/each} * {/each} - *
    - * ``` + *
+ * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `createInfiniteQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link createInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -119,46 +126,51 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `createInfiniteQuery`. - * These options can be shared across `createInfiniteQuery` calls and imperative APIs such as - * `queryClient.infiniteQuery`. `options.queryKey` is required and is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `createInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link createInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `createInfiniteQuery`. These options can be shared across + * `createInfiniteQuery` calls and imperative APIs such as + * `queryClient.infiniteQuery`. `options.queryKey` is required and is the query + * key to generate options for. + * * @example - * A parameterized factory, so the same options object can be reused per `postId`: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *
    - * {#each query.data.pages as page} - * {#each page.comments as comment (comment.id)} - *
  • {comment.text}
  • - * {/each} - * {/each} + * {#each query.data.pages as page} + * {#each page.comments as comment (comment.id)} + *
  • {comment.text}
  • + * {/each} + * {/each} *
- * {/if} - * ``` + * {/if} + * ``` + * + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `createInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link createInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, diff --git a/packages/svelte-query/src/mutationOptions.ts b/packages/svelte-query/src/mutationOptions.ts index 3510f7d2791..e2a47238a0a 100644 --- a/packages/svelte-query/src/mutationOptions.ts +++ b/packages/svelte-query/src/mutationOptions.ts @@ -2,32 +2,35 @@ import type { DefaultError, WithRequired } from '@tanstack/query-core' import type { CreateMutationOptions } from './types.js' /** - * You can generally pass everything to `mutationOptions` that you can also pass to `createMutation`. This - * overload requires `mutationKey`, so the resulting options can be looked up elsewhere (e.g. with - * `useMutationState`). - * @param options - The options to use — everything you can pass to `createMutation`, with `mutationKey` set. - * @returns The same options object. - * @see {@link createMutation} to run a mutation with these options. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `createMutation`. This overload requires `mutationKey`, so the resulting + * options can be looked up elsewhere (e.g. with `useMutationState`). + * * @example - * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: - * ```svelte - * + * * - * {#if pending.length > 0} + * {#if pending.length > 0} * Saving… - * {/if} - * ``` + * {/if} + * ``` + * + * @param options - The options to use — everything you can pass to + * `createMutation`, with `mutationKey` set. + * @returns The same options object. + * @see {@link createMutation} to run a mutation with these options. */ export function mutationOptions< TData = unknown, @@ -45,24 +48,28 @@ export function mutationOptions< > /** - * You can generally pass everything to `mutationOptions` that you can also pass to `createMutation`. - * @param options - The options to use — everything you can pass to `createMutation`. - * @returns The same options object. - * @see {@link createMutation} to run a mutation with these options. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `createMutation`. + * * @example - * ```svelte - * + * * - * - * ``` + * + * ``` + * + * @param options - The options to use — everything you can pass to + * `createMutation`. + * @returns The same options object. + * @see {@link createMutation} to run a mutation with these options. */ export function mutationOptions< TData = unknown, diff --git a/packages/svelte-query/src/queryOptions.ts b/packages/svelte-query/src/queryOptions.ts index 4a67683bf2a..42783233809 100644 --- a/packages/svelte-query/src/queryOptions.ts +++ b/packages/svelte-query/src/queryOptions.ts @@ -8,8 +8,9 @@ import type { import type { CreateQueryOptions } from './types.js' /** - * The options accepted by the `queryOptions` overload selected when `initialData` is omitted or may be - * `undefined` — `data` may be `undefined` while the query is `pending`. + * The options accepted by the `queryOptions` overload selected when + * `initialData` is omitted or may be `undefined` — `data` may be `undefined` + * while the query is `pending`. */ export type UndefinedInitialDataOptions< TQueryFnData = unknown, @@ -24,8 +25,9 @@ export type UndefinedInitialDataOptions< } /** - * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never - * `undefined` (unless a `select` changes `TData` to include `undefined`). + * The options accepted by the `queryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). */ export type DefinedInitialDataOptions< TQueryFnData = unknown, @@ -39,41 +41,46 @@ export type DefinedInitialDataOptions< } /** - * You can generally pass everything to `queryOptions` that you can also pass to `createQuery`. These options - * can be shared across `createQuery` calls and imperative APIs such as `queryClient.query`. `options.queryKey` - * is required and is the query key to generate options for. + * You can generally pass everything to `queryOptions` that you can also pass to + * `createQuery`. These options can be shared across `createQuery` calls and + * imperative APIs such as `queryClient.query`. `options.queryKey` is required + * and is the query key to generate options for. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataOptions} to use — everything you can pass to `createQuery`, - * with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link createQuery} to run a query with these options. * @example - * ```svelte - * + * * - * {#if query.isError} + * {#if query.isError} * Error: {query.error.message} - * {/if} - *
    + * {/if} + *
      * {#each query.data as post (post.id)} - *
    • {post.title}
    • + *
    • {post.title}
    • * {/each} - *
    - * ``` + *
+ * ``` + * + * @param options - The {@link DefinedInitialDataOptions} to use — everything + * you can pass to `createQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link createQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, @@ -86,37 +93,42 @@ export function queryOptions< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `createQuery`. These options - * can be shared across `createQuery` calls and imperative APIs such as `queryClient.query`. `options.queryKey` - * is required and is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataOptions} to use — everything you can pass to `createQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link createQuery} to run a query with these options. + * You can generally pass everything to `queryOptions` that you can also pass to + * `createQuery`. These options can be shared across `createQuery` calls and + * imperative APIs such as `queryClient.query`. `options.queryKey` is required + * and is the query key to generate options for. + * * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```svelte - * + * * - * {#if query.isPending} + * {#if query.isPending} * Loading... - * {:else if query.isError} + * {:else if query.isError} * Error: {query.error.message} - * {:else} + * {:else} *

{query.data.title}

- * {/if} - * ``` + * {/if} + * ``` + * + * @param options - The {@link UndefinedInitialDataOptions} to use — everything + * you can pass to `createQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link createQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, diff --git a/packages/svelte-query/src/types.ts b/packages/svelte-query/src/types.ts index d11b84ab465..0d2128eaa77 100644 --- a/packages/svelte-query/src/types.ts +++ b/packages/svelte-query/src/types.ts @@ -20,8 +20,8 @@ import type { } from '@tanstack/query-core' /** - * A function that returns a value. Options passed as an accessor are read inside reactive contexts, so they - * update when the state they read changes. + * A function that returns a value. Options passed as an accessor are read + * inside reactive contexts, so they update when the state they read changes. */ export type Accessor = () => T @@ -105,9 +105,10 @@ export type CreateMutationOptions< > /** - * The type of `mutate`, as returned by `createMutation`. Forwards the variables (and an optional per-call - * `onSuccess`/`onError`/`onSettled`) to the underlying `mutate` call. Fire-and-forget — errors are surfaced - * through the mutation result, not thrown. + * The type of `mutate`, as returned by `createMutation`. Forwards the variables + * (and an optional per-call `onSuccess`/`onError`/`onSettled`) to the + * underlying `mutate` call. Fire-and-forget — errors are surfaced through the + * mutation result, not thrown. */ export type CreateMutateFunction< TData = unknown, @@ -121,8 +122,8 @@ export type CreateMutateFunction< ) => void /** - * The type of `mutateAsync`, as returned by `createMutation`. Similar to {@link CreateMutateFunction}, but - * returns a promise which can be awaited. + * The type of `mutateAsync`, as returned by `createMutation`. Similar to + * {@link CreateMutateFunction}, but returns a promise which can be awaited. */ export type CreateMutateAsyncFunction< TData = unknown, @@ -132,9 +133,9 @@ export type CreateMutateAsyncFunction< > = MutateFunction /** - * The result of `createMutation`. Same as {@link MutationObserverResult} from `@tanstack/query-core`, with - * `mutate` narrowed to the fire-and-forget {@link CreateMutateFunction} signature, plus the added - * `mutateAsync`. + * The result of `createMutation`. Same as {@link MutationObserverResult} from + * `@tanstack/query-core`, with `mutate` narrowed to the fire-and-forget + * {@link CreateMutateFunction} signature, plus the added `mutateAsync`. */ export type CreateBaseMutationResult< TData = unknown, @@ -162,8 +163,8 @@ export type CreateMutationResult< > = CreateBaseMutationResult /** - * Infers the `Mutation` type passed to `useMutationState`'s `select` from the `MutationState` type it - * returns, falling back to `Mutation` otherwise. + * Infers the `Mutation` type passed to `useMutationState`'s `select` from the + * `MutationState` type it returns, falling back to `Mutation` otherwise. */ export type MutationTypeFromResult = [TResult] extends [ MutationState< @@ -182,26 +183,19 @@ export type MutationStateOptions< TMutation extends Mutation = MutationTypeFromResult, > = { - /** - * The filters that select the mutations to return the state of. - */ + /** The filters that select the mutations to return the state of. */ filters?: MutationFilters /** - * Maps each matching mutation to the value returned for it. Defaults to the mutation's `state`. + * Maps each matching mutation to the value returned for it. Defaults to the + * mutation's `state`. */ select?: (mutation: TMutation) => TResult } -/** - * The props accepted by `QueryClientProvider`. - */ +/** The props accepted by `QueryClientProvider`. */ export type QueryClientProviderProps = { - /** - * The `QueryClient` to provide to the children. - */ + /** The `QueryClient` to provide to the children. */ client: QueryClient - /** - * The children that can use the provided `QueryClient`. - */ + /** The children that can use the provided `QueryClient`. */ children: Snippet } diff --git a/packages/svelte-query/src/useHydrate.ts b/packages/svelte-query/src/useHydrate.ts index 919b2846df3..9155ed76690 100644 --- a/packages/svelte-query/src/useHydrate.ts +++ b/packages/svelte-query/src/useHydrate.ts @@ -3,30 +3,34 @@ import { useQueryClient } from './useQueryClient.js' import type { HydrateOptions, QueryClient } from '@tanstack/query-core' /** - * Adds a previously dehydrated `state` into the `queryClient` (from the nearest context, or the one - * passed explicitly). If the client already contains data, the new queries will be intelligently merged based - * on update timestamp. `HydrationBoundary` wraps this — use it directly only if you need to hydrate from your - * own component instead. - * @param state - The dehydrated state to hydrate into the cache, as produced by `dehydrate`. - * @param options - {@link HydrateOptions} to control the hydration. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. + * Adds a previously dehydrated `state` into the `queryClient` (from the nearest + * context, or the one passed explicitly). If the client already contains data, + * the new queries will be intelligently merged based on update timestamp. + * `HydrationBoundary` wraps this — use it directly only if you need to hydrate + * from your own component instead. + * * @example - * Server-side prefetch handed off to the client via `dehydrate` — `dehydratedState` would typically come - * from a server load function that prefetched with `queryClient.query` and called `dehydrate(queryClient)`: - * ```svelte - * + * * - * + * * - * - * ``` + * + * ``` + * + * @param state - The dehydrated state to hydrate into the cache, as produced by + * `dehydrate`. + * @param options - {@link HydrateOptions} to control the hydration. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. */ export function useHydrate( state?: unknown, diff --git a/packages/svelte-query/src/useIsFetching.svelte.ts b/packages/svelte-query/src/useIsFetching.svelte.ts index 05be0083c04..ad795f59936 100644 --- a/packages/svelte-query/src/useIsFetching.svelte.ts +++ b/packages/svelte-query/src/useIsFetching.svelte.ts @@ -3,39 +3,44 @@ import { useQueryClient } from './useQueryClient.js' import type { QueryClient, QueryFilters } from '@tanstack/query-core' /** - * The `useIsFetching` function returns the `number` of the queries that your application is loading or - * fetching in the background (useful for app-wide loading indicators). - * @param filters - {@link QueryFilters} to narrow down which queries to count. Omit to count every fetching - * query. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns A reactive value — read `.current` to get how many matching queries are currently fetching. + * The `useIsFetching` function returns the `number` of the queries that your + * application is loading or fetching in the background (useful for app-wide + * loading indicators). + * * @example - * ```svelte - * + * * - * {#if isFetchingPosts.current} + * {#if isFetchingPosts.current} * Refreshing posts... - * {/if} - * ``` + * {/if} + * ``` + * * @example - * A global loading indicator for any query fetching in the background, not just the ones on screen: - * ```svelte - * + * * - * {#if isFetching.current} + * {#if isFetching.current} *
Queries are fetching in the background...
- * {/if} - * ``` + * {/if} + * ``` + * + * @param filters - {@link QueryFilters} to narrow down which queries to count. + * Omit to count every fetching query. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns A reactive value — read `.current` to get how many matching queries + * are currently fetching. */ export function useIsFetching( filters?: QueryFilters, diff --git a/packages/svelte-query/src/useIsMutating.svelte.ts b/packages/svelte-query/src/useIsMutating.svelte.ts index 8dc58f96f03..8ec0c285981 100644 --- a/packages/svelte-query/src/useIsMutating.svelte.ts +++ b/packages/svelte-query/src/useIsMutating.svelte.ts @@ -3,25 +3,30 @@ import { ReactiveValue } from './containers.svelte.js' import type { MutationFilters, QueryClient } from '@tanstack/query-core' /** - * `useIsMutating` is an optional function that returns the `number` of mutations that your application is - * running (useful for app-wide loading indicators). - * @param filters - {@link MutationFilters} to narrow down which mutations to count. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns A reactive value — read `.current` to get how many matching mutations are currently running. + * `useIsMutating` is an optional function that returns the `number` of + * mutations that your application is running (useful for app-wide loading + * indicators). + * * @example - * ```svelte - * + * * - * {#if isMutatingPosts.current} + * {#if isMutatingPosts.current} * Saving posts... - * {/if} - * ``` + * {/if} + * ``` + * + * @param filters - {@link MutationFilters} to narrow down which mutations to + * count. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns A reactive value — read `.current` to get how many matching + * mutations are currently running. */ export function useIsMutating( filters?: MutationFilters, diff --git a/packages/svelte-query/src/useIsRestoring.ts b/packages/svelte-query/src/useIsRestoring.ts index 34ce5695bff..66f12268206 100644 --- a/packages/svelte-query/src/useIsRestoring.ts +++ b/packages/svelte-query/src/useIsRestoring.ts @@ -2,23 +2,26 @@ import { getIsRestoringContext } from './context.js' import type { Box } from './containers.svelte.js' /** - * If you are using `PersistQueryClientProvider`, you can also use the `useIsRestoring` function alongside it to - * check if a restore is currently in progress. `createQuery` and friends also check this internally to avoid - * race conditions between the restore and mounting queries. - * @returns A reactive box — read `.current` for `true` while a persisted client is being restored, `false` - * otherwise. + * If you are using `PersistQueryClientProvider`, you can also use the + * `useIsRestoring` function alongside it to check if a restore is currently in + * progress. `createQuery` and friends also check this internally to avoid race + * conditions between the restore and mounting queries. + * * @example - * ```svelte - * + * * - * {#if isRestoring.current} + * {#if isRestoring.current} *
Restoring cached data...
- * {/if} - * ``` + * {/if} + * ``` + * + * @returns A reactive box — read `.current` for `true` while a persisted client + * is being restored, `false` otherwise. */ export function useIsRestoring(): Box { return getIsRestoringContext() diff --git a/packages/svelte-query/src/useMutationState.svelte.ts b/packages/svelte-query/src/useMutationState.svelte.ts index aa0bbd70ed8..794fe1b6cf7 100644 --- a/packages/svelte-query/src/useMutationState.svelte.ts +++ b/packages/svelte-query/src/useMutationState.svelte.ts @@ -9,10 +9,12 @@ import type { import type { MutationStateOptions, MutationTypeFromResult } from './types.js' /** - * Collects the mutations in the cache that match `options.filters`, mapped with `options.select` - * (or to their state, by default). + * Collects the mutations in the cache that match `options.filters`, mapped with + * `options.select` (or to their state, by default). + * * @param mutationCache - The mutation cache to read. - * @param options - The `filters` to match and the `select` function to map each mutation with. + * @param options - The `filters` to match and the `select` function to map each + * mutation with. * @returns The selected value of every matching mutation. */ function getResult< @@ -34,71 +36,75 @@ function getResult< } /** - * `useMutationState` is a function that gives you access to all mutations in the `MutationCache`. You can pass - * `filters` ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the mutation - * state. - * @param options - The `filters` to narrow down matched mutations, and an optional `select` to transform the - * mutation state. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns An Array of whatever `select` returns for each matching mutation. + * `useMutationState` is a function that gives you access to all mutations in + * the `MutationCache`. You can pass `filters` ({@link MutationFilters}) to + * narrow down your mutations, and `select` to transform the mutation state. + * * @example - * Get all variables of all running mutations: - * ```svelte - * + * + * + * {pendingVariables.length} posts saving... + * ``` * - * {pendingVariables.length} posts saving... - * ``` * @example - * Get all data for specific mutations via the `mutationKey`: - * ```svelte - * + * * - * - * ``` + * + * ``` + * * @example - * Access the latest mutation data via the `mutationKey`. Each invocation of `mutate` adds a new entry to the - * mutation cache for `gcTime` milliseconds — check the last item that `useMutationState` returns to get the - * latest successful mutation (the `status: 'success'` filter above excludes pending/errored ones): - * ```svelte - * + * + * + * {latestSavedPost ? 'Saved' : 'Nothing saved yet'} + * ``` * - * {latestSavedPost ? 'Saved' : 'Nothing saved yet'} - * ``` + * @param options - The `filters` to narrow down matched mutations, and an + * optional `select` to transform the mutation state. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns An Array of whatever `select` returns for each matching mutation. */ export function useMutationState< TResult = MutationState, diff --git a/packages/svelte-query/src/useQueryClient.ts b/packages/svelte-query/src/useQueryClient.ts index d6786305375..b2947db56a7 100644 --- a/packages/svelte-query/src/useQueryClient.ts +++ b/packages/svelte-query/src/useQueryClient.ts @@ -3,23 +3,25 @@ import type { QueryClient } from '@tanstack/query-core' /** * The `useQueryClient` function returns the current `QueryClient` instance. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one from the nearest context will - * be used. - * @returns The current `QueryClient` instance. - * @throws {Error} If no `queryClient` argument is passed and no `QueryClientProvider` is found in the - * component tree. + * * @example - * ```svelte - * - * ``` + * + * ``` + * + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one from the nearest context will be used. + * @returns The current `QueryClient` instance. + * @throws {Error} If no `queryClient` argument is passed and no + * `QueryClientProvider` is found in the component tree. */ export function useQueryClient(queryClient?: QueryClient): QueryClient { if (queryClient) return queryClient diff --git a/packages/svelte-query/src/utils.svelte.ts b/packages/svelte-query/src/utils.svelte.ts index 83054d6f44b..151e8848978 100644 --- a/packages/svelte-query/src/utils.svelte.ts +++ b/packages/svelte-query/src/utils.svelte.ts @@ -2,7 +2,9 @@ import { untrack } from 'svelte' // modified from the great https://github.com/svecosystem/runed /** * Runs an effect after (`'post'`) or before (`'pre'`) the DOM updates. - * @param flush - When to run the effect: `'post'` uses `$effect`, `'pre'` uses `$effect.pre`. + * + * @param flush - When to run the effect: `'post'` uses `$effect`, `'pre'` uses + * `$effect.pre`. * @param effect - The effect to run. It may return a cleanup function. */ function runEffect( @@ -20,12 +22,16 @@ function runEffect( } type Getter = () => T /** - * Runs `effect` whenever the reactive state read by `sources` changes, even if they return the - * same values, skipping the first run. The effect receives the new and previous values, and is - * called untracked, so only `sources` are tracked. + * Runs `effect` whenever the reactive state read by `sources` changes, even if + * they return the same values, skipping the first run. The effect receives the + * new and previous values, and is called untracked, so only `sources` are + * tracked. + * * @param sources - The getter, or array of getters, to watch. - * @param flush - Whether to run after (`'post'`) or before (`'pre'`) the DOM updates. - * @param effect - Called with the new and previous values. It may return a cleanup function. + * @param flush - Whether to run after (`'post'`) or before (`'pre'`) the DOM + * updates. + * @param effect - Called with the new and previous values. It may return a + * cleanup function. */ export const watchChanges = ( sources: Getter | Array>, diff --git a/packages/vue-query-devtools/src/types.ts b/packages/vue-query-devtools/src/types.ts index 87044867e89..3b7d60ccf07 100644 --- a/packages/vue-query-devtools/src/types.ts +++ b/packages/vue-query-devtools/src/types.ts @@ -7,93 +7,96 @@ import type { import type { QueryClient } from '@tanstack/vue-query' /** - * The props of `VueQueryDevtools`, which renders the devtools with a toggle button that opens them. + * The props of `VueQueryDevtools`, which renders the devtools with a toggle + * button that opens them. */ export interface DevtoolsOptions { - /** - * Set this true if you want the dev tools to default to being open - */ + /** Set this true if you want the dev tools to default to being open */ initialIsOpen?: boolean /** * The position of the TanStack logo to open and close the devtools panel. * 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'relative' + * * @defaultValue bottom-right */ buttonPosition?: DevtoolsButtonPosition /** - * The position of the Vue Query devtools panel. - * 'top' | 'bottom' | 'left' | 'right' + * The position of the Vue Query devtools panel. 'top' | 'bottom' | 'left' | + * 'right' + * * @defaultValue bottom */ position?: DevtoolsPosition - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot - /** - * Set this to true to hide disabled queries from the devtools panel. - */ + /** Set this to true to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Set this to 'light', 'dark', or 'system' to change the theme of the + * devtools panel. + * * @defaultValue system */ theme?: Theme } /** - * The props of `VueQueryDevtoolsPanel`, which renders the devtools panel inline. + * The props of `VueQueryDevtoolsPanel`, which renders the devtools panel + * inline. */ export interface DevtoolsPanelOptions { - /** - * Custom instance of QueryClient - */ + /** Custom instance of QueryClient */ client?: QueryClient - /** - * Use this so you can define custom errors that can be shown in the devtools. - */ + /** Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array /** - * Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles. + * Use this to pass a nonce to the style tag that is added to the document + * head. This is useful if you are using a Content Security Policy (CSP) nonce + * to allow inline styles. */ styleNonce?: string /** - * Use this to pass a shadow DOM target to the devtools so that the styles will be applied - * within the shadow DOM instead of within the head tag in the light DOM. + * Use this to pass a shadow DOM target to the devtools so that the styles + * will be applied within the shadow DOM instead of within the head tag in the + * light DOM. */ shadowDOMTarget?: ShadowRoot /** * Custom styles for the devtools panel + * + * @example + * ;({ height: '100%' }) + * + * @example + * ;({ height: '100%', width: '100%' }) + * * @default { height: '500px' } - * @example { height: '100%' } - * @example { height: '100%', width: '100%' } */ style?: Partial - /** - * Callback function that is called when the devtools panel is closed - */ + /** Callback function that is called when the devtools panel is closed */ onClose?: () => void - /** - * Set this to true to hide disabled queries from the devtools panel. - */ + /** Set this to true to hide disabled queries from the devtools panel. */ hideDisabledQueries?: boolean /** - * Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel. + * Set this to 'light', 'dark', or 'system' to change the theme of the + * devtools panel. + * * @defaultValue system */ theme?: Theme diff --git a/packages/vue-query/src/devtools/devtools.ts b/packages/vue-query/src/devtools/devtools.ts index 30caa3cd83f..25772c931ef 100644 --- a/packages/vue-query/src/devtools/devtools.ts +++ b/packages/vue-query/src/devtools/devtools.ts @@ -15,8 +15,9 @@ const pluginId = 'vue-query' const pluginName = 'Vue Query' /** - * Registers the Vue Query plugin with the Vue devtools, adding a query inspector and a timeline - * layer for query cache events. + * Registers the Vue Query plugin with the Vue devtools, adding a query + * inspector and a timeline layer for query cache events. + * * @param app - The Vue app instance. * @param queryClient - The client whose query cache is shown in the devtools. */ diff --git a/packages/vue-query/src/devtools/utils.ts b/packages/vue-query/src/devtools/utils.ts index ff673d413ca..27bf2e5d8f1 100644 --- a/packages/vue-query/src/devtools/utils.ts +++ b/packages/vue-query/src/devtools/utils.ts @@ -11,8 +11,9 @@ enum QueryState { } /** - * Returns the devtools state of a query: fetching, paused, inactive (no observers), stale, or fresh, - * checked in that order. + * Returns the devtools state of a query: fetching, paused, inactive (no + * observers), stale, or fresh, checked in that order. + * * @param query - The query to check. * @returns A `QueryState` value, used to label, color, and sort the query. */ @@ -35,6 +36,7 @@ export function getQueryState(query: Query): QueryState { /** * Returns the label of a query's devtools state, shown in the inspector. + * * @param query - The query to label. * @returns `'fetching'`, `'paused'`, `'stale'`, `'inactive'`, or `'fresh'`. */ @@ -59,6 +61,7 @@ export function getQueryStateLabel(query: Query): string { /** * Returns the text color of a query's state label in the inspector. + * * @param query - The query to get the color for. * @returns Black for stale queries, otherwise white, as a hex number. */ @@ -74,6 +77,7 @@ export function getQueryStatusFg(query: Query): number { /** * Returns the background color of a query's state label in the inspector. + * * @param query - The query to get the color for. * @returns The color for the query's state, as a hex number. */ diff --git a/packages/vue-query/src/infiniteQueryOptions.ts b/packages/vue-query/src/infiniteQueryOptions.ts index e6ae5ca0839..41ebf30f107 100644 --- a/packages/vue-query/src/infiniteQueryOptions.ts +++ b/packages/vue-query/src/infiniteQueryOptions.ts @@ -8,14 +8,19 @@ import type { import type { UseInfiniteQueryOptions } from './useInfiniteQuery' /** - * The options accepted by the `infiniteQueryOptions` overload selected when no `initialData` is set — `data` - * may be `undefined` while the query is `pending`. - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type UndefinedInitialDataInfiniteOptions< TQueryFnData, @@ -34,14 +39,19 @@ export type UndefinedInitialDataInfiniteOptions< } /** - * The options accepted by the `infiniteQueryOptions` overload selected when `initialData` is set — `data` is - * never `undefined` (unless a `select` changes `TData` to include `undefined`). - * @template TQueryFnData - The type of a single page, as your `queryFn` resolves it. + * The options accepted by the `infiniteQueryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * + * @template TQueryFnData - The type of a single page, as your `queryFn` + * resolves it. * @template TError - The type of errors your `queryFn` may throw. - * @template TData - The type `data` ends up as after `select` runs — defaults to `InfiniteData`, - * the shape of all fetched pages plus their page params. + * @template TData - The type `data` ends up as after `select` runs — defaults + * to `InfiniteData`, the shape of all fetched pages plus their + * page params. * @template TQueryKey - The type of your `queryKey`. - * @template TPageParam - The type of the parameter passed to `queryFn` to fetch a given page. + * @template TPageParam - The type of the parameter passed to `queryFn` to fetch + * a given page. */ export type DefinedInitialDataInfiniteOptions< TQueryFnData, @@ -57,11 +67,12 @@ export type DefinedInitialDataInfiniteOptions< TPageParam > & { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. */ initialData: | NonUndefinedGuard> @@ -69,28 +80,32 @@ export type DefinedInitialDataInfiniteOptions< } /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`. - * These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`. - * `options.queryKey` is required and is the query key to generate options for. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `useInfiniteQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link useInfiniteQuery} to run an infinite query with these options. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `useInfiniteQuery`. These options can be shared across hooks and + * imperative APIs such as `queryClient.infiniteQuery`. `options.queryKey` is + * required and is the query key to generate options for. + * * @example - * ```vue - * + * ``` * - * const { data, isError, error, fetchNextPage } = useInfiniteQuery(projectsOptions) - * - * ``` + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, @@ -116,34 +131,39 @@ export function infiniteQueryOptions< QueryKeyWithDataTag, TError> /** - * You can generally pass everything to `infiniteQueryOptions` that you can also pass to `useInfiniteQuery`. - * These options can be shared across hooks and imperative APIs such as `queryClient.infiniteQuery`. - * `options.queryKey` is required and is the query key to generate options for. + * You can generally pass everything to `infiniteQueryOptions` that you can also + * pass to `useInfiniteQuery`. These options can be shared across hooks and + * imperative APIs such as `queryClient.infiniteQuery`. `options.queryKey` is + * required and is the query key to generate options for. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `useInfiniteQuery`, with `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link useInfiniteQuery} to run an infinite query with these options. * @example - * ```vue - * - * ``` + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery(projectsOptions) + * + * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useInfiniteQuery} to run an infinite query with these options. */ export function infiniteQueryOptions< TQueryFnData, diff --git a/packages/vue-query/src/mutationCache.ts b/packages/vue-query/src/mutationCache.ts index 8a5ea68457f..27d34e66171 100644 --- a/packages/vue-query/src/mutationCache.ts +++ b/packages/vue-query/src/mutationCache.ts @@ -8,9 +8,11 @@ import type { import type { MaybeRefDeep } from './types' /** - * Vue-aware subclass of `@tanstack/query-core`'s `MutationCache`. `find`/`findAll` also accept a - * {@link MaybeRefDeep} filters object, so `ref`s can be passed directly without unwrapping. Access it via - * `queryClient.getMutationCache()` — `QueryClient` constructs one of these by default. + * Vue-aware subclass of `@tanstack/query-core`'s `MutationCache`. + * `find`/`findAll` also accept a {@link MaybeRefDeep} filters object, so `ref`s + * can be passed directly without unwrapping. Access it via + * `queryClient.getMutationCache()` — `QueryClient` constructs one of these by + * default. */ export class MutationCache extends MC { override find< diff --git a/packages/vue-query/src/mutationOptions.ts b/packages/vue-query/src/mutationOptions.ts index 90dc8485a6f..8b4a63f1182 100644 --- a/packages/vue-query/src/mutationOptions.ts +++ b/packages/vue-query/src/mutationOptions.ts @@ -2,36 +2,40 @@ import type { DefaultError, WithRequired } from '@tanstack/query-core' import type { MutationOptions } from './types' /** - * You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. A - * `mutationKey` is required on this overload so the mutation can be looked up later, e.g. with - * `useMutationState`. - * - * Unlike a `queryKey` property on a query's options (e.g. `queryOptions({ queryKey: [...] })`), `mutationKey` - * entries that are reactive getters (`() => id.value`) are never unwrapped — the getter function itself is - * stored as the entry, rather than its current value. `ref` entries are still unwrapped normally. - * @param options - The mutation options to use, identical to what you'd pass to `useMutation`, with a - * required `mutationKey`. - * @returns The same options object, unchanged. - * @see {@link useMutation} to run the mutation these options describe. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `useMutation`. A `mutationKey` is required on this overload so the + * mutation can be looked up later, e.g. with `useMutationState`. + * + * Unlike a `queryKey` property on a query's options (e.g. `queryOptions({ + * queryKey: [...] })`), `mutationKey` entries that are reactive getters (`() => + * id.value`) are never unwrapped — the getter function itself is stored as the + * entry, rather than its current value. `ref` entries are still unwrapped + * normally. + * * @example - * Looking the mutation up elsewhere via its `mutationKey`, e.g. for a global "saving…" indicator: - * ```vue - * - * ``` + * }) + * const isCreatingPost = computed(() => creatingPosts.value.length > 0) + * + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `useMutation`, with a required `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, @@ -49,33 +53,37 @@ export function mutationOptions< > /** - * Same as the plain-object overload with a required `mutationKey`, but for options that close over reactive - * state (`ref`s read inside the function body). Wrap them in a getter so `useMutation` and the other consumers - * always read the current values instead of the ones captured when the options were created. - * @param options - A function returning the mutation options to use, with a required `mutationKey`, - * re-evaluated on demand. - * @returns A function that returns the same options object, unchanged. - * @see {@link useMutation} to run the mutation these options describe. + * Same as the plain-object overload with a required `mutationKey`, but for + * options that close over reactive state (`ref`s read inside the function + * body). Wrap them in a getter so `useMutation` and the other consumers always + * read the current values instead of the ones captured when the options were + * created. + * * @example - * ```vue - * + * const mutation = useMutation(createPostOptions) + * * - * + * ``` + * + * @param options - A function returning the mutation options to use, with a + * required `mutationKey`, re-evaluated on demand. + * @returns A function that returns the same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, @@ -93,31 +101,36 @@ export function mutationOptions< > /** - * You can generally pass everything to `mutationOptions` that you can also pass to `useMutation`. No - * `mutationKey` is required on this overload — use this when you don't need to target the mutation via a - * `mutationKey` filter later (e.g. with `useMutationState`); it can still be observed through other filters, - * such as `status`. - * @param options - The mutation options to use, identical to what you'd pass to `useMutation`, without a - * `mutationKey`. - * @returns The same options object, unchanged. - * @remarks See the other overload's example for looking a mutation up via `useMutationState`. - * @see {@link useMutation} to run the mutation these options describe. + * You can generally pass everything to `mutationOptions` that you can also pass + * to `useMutation`. No `mutationKey` is required on this overload — use this + * when you don't need to target the mutation via a `mutationKey` filter later + * (e.g. with `useMutationState`); it can still be observed through other + * filters, such as `status`. + * + * @remarks + * See the other overload's example for looking a mutation up via + * `useMutationState`. * @example - * ```vue - * + * const mutation = useMutation(createPostOptions) + * * - * + * ``` + * + * @param options - The mutation options to use, identical to what you'd pass to + * `useMutation`, without a `mutationKey`. + * @returns The same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, @@ -135,32 +148,35 @@ export function mutationOptions< > /** - * Same as the plain-object overload without a `mutationKey`, but for options that close over reactive state - * (`ref`s read inside the function body). Wrap them in a getter so `useMutation` and the other consumers - * always read the current values instead of the ones captured when the options were created. - * @param options - A function returning the mutation options to use, without a `mutationKey`, re-evaluated on - * demand. - * @returns A function that returns the same options object, unchanged. - * @see {@link useMutation} to run the mutation these options describe. + * Same as the plain-object overload without a `mutationKey`, but for options + * that close over reactive state (`ref`s read inside the function body). Wrap + * them in a getter so `useMutation` and the other consumers always read the + * current values instead of the ones captured when the options were created. + * * @example - * ```vue - * + * const mutation = useMutation(createPostOptions) + * * - * + * ``` + * + * @param options - A function returning the mutation options to use, without a + * `mutationKey`, re-evaluated on demand. + * @returns A function that returns the same options object, unchanged. + * @see {@link useMutation} to run the mutation these options describe. */ export function mutationOptions< TData = unknown, diff --git a/packages/vue-query/src/queryCache.ts b/packages/vue-query/src/queryCache.ts index d870fa96a8e..a9457d8ac61 100644 --- a/packages/vue-query/src/queryCache.ts +++ b/packages/vue-query/src/queryCache.ts @@ -9,9 +9,10 @@ import type { import type { MaybeRefDeep } from './types' /** - * Vue-aware subclass of `@tanstack/query-core`'s `QueryCache`. `find`/`findAll` also accept a - * {@link MaybeRefDeep} filters object, so `ref`s can be passed directly without unwrapping. Access it via - * `queryClient.getQueryCache()` — `QueryClient` constructs one of these by default. + * Vue-aware subclass of `@tanstack/query-core`'s `QueryCache`. `find`/`findAll` + * also accept a {@link MaybeRefDeep} filters object, so `ref`s can be passed + * directly without unwrapping. Access it via `queryClient.getQueryCache()` — + * `QueryClient` constructs one of these by default. */ export class QueryCache extends QC { override find< diff --git a/packages/vue-query/src/queryClient.ts b/packages/vue-query/src/queryClient.ts index 475fa27bed3..372643cc8f5 100644 --- a/packages/vue-query/src/queryClient.ts +++ b/packages/vue-query/src/queryClient.ts @@ -35,18 +35,23 @@ import type { } from '@tanstack/query-core' /** - * Vue-aware subclass of `@tanstack/query-core`'s `QueryClient`. Methods that accept `options` (such as - * `CancelOptions` or `InvalidateOptions`) or filters (such as the `QueryFilters` accepted by - * `invalidateQueries`) also accept a {@link MaybeRefDeep} version of it, so you can pass `ref`s directly - * without unwrapping them yourself — e.g. `queryClient.invalidateQueries({ queryKey: ['post', myRef] })`. + * Vue-aware subclass of `@tanstack/query-core`'s `QueryClient`. Methods that + * accept `options` (such as `CancelOptions` or `InvalidateOptions`) or filters + * (such as the `QueryFilters` accepted by `invalidateQueries`) also accept a + * {@link MaybeRefDeep} version of it, so you can pass `ref`s directly without + * unwrapping them yourself — e.g. `queryClient.invalidateQueries({ queryKey: + * ['post', myRef] })`. * - * `ref` entries in a `queryKey` are unwrapped this way on every method, but reactive getter entries - * (`() => id.value`) are only unwrapped when the `queryKey` is passed as a `queryKey` property of a - * filters/options object (e.g. `invalidateQueries({ queryKey: ['post', idGetter] })`) — methods like - * `getQueryData` that take the `queryKey` array as their own argument do not unwrap getter entries there, - * and the getter function itself ends up in the cache key. + * `ref` entries in a `queryKey` are unwrapped this way on every method, but + * reactive getter entries (`() => id.value`) are only unwrapped when the + * `queryKey` is passed as a `queryKey` property of a filters/options object + * (e.g. `invalidateQueries({ queryKey: ['post', idGetter] })`) — methods like + * `getQueryData` that take the `queryKey` array as their own argument do not + * unwrap getter entries there, and the getter function itself ends up in the + * cache key. * - * Install one on your app with `VueQueryPlugin`, or retrieve it with `useQueryClient`. + * Install one on your app with `VueQueryPlugin`, or retrieve it with + * `useQueryClient`. */ export class QueryClient extends QC { constructor(config: QueryClientConfig = {}) { @@ -59,8 +64,9 @@ export class QueryClient extends QC { } /** - * `true` while a `clientPersister` passed to `VueQueryPlugin` is restoring the cache. Queries don't fetch - * while this is `true`. Defaults to `false` if no persister is configured. + * `true` while a `clientPersister` passed to `VueQueryPlugin` is restoring + * the cache. Queries don't fetch while this is `true`. Defaults to `false` if + * no persister is configured. */ isRestoring?: Ref = ref(false) @@ -89,13 +95,16 @@ export class QueryClient extends QC { } /** - * Returns the cached data of a query, or fetches it if there is none. With `revalidateIfStale`, - * stale cached data is also refetched in the background. - * @param options - The query options. If the query has no cached data yet, it is fetched with - * these options. - * @returns A promise that resolves to the cached data, or to the fetched data if nothing was - * cached yet. - * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) instead. This method will be removed in the next major version. + * Returns the cached data of a query, or fetches it if there is none. With + * `revalidateIfStale`, stale cached data is also refetched in the + * background. + * + * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) + * instead. This method will be removed in the next major version. + * @param options - The query options. If the query has no cached data yet, it + * is fetched with these options. + * @returns A promise that resolves to the cached data, or to the fetched data + * if nothing was cached yet. */ override ensureQueryData< TQueryFnData, @@ -107,7 +116,9 @@ export class QueryClient extends QC { ): Promise /** * {@inheritDoc QueryClient.ensureQueryData:0} - * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) instead. This method will be removed in the next major version. + * + * @deprecated Use queryClient.query({ ...options, staleTime: 'static' }) + * instead. This method will be removed in the next major version. */ override ensureQueryData< TQueryFnData, @@ -332,13 +343,15 @@ export class QueryClient extends QC { } /** - * Fetches and caches a query, or returns its cached data if it isn't stale. Unlike in observers, - * the fetch isn't retried unless `retry` is set. - * @param options - The query options, including the `queryKey` and the `queryFn` used if the - * query needs to fetch. - * @returns A promise that resolves to the cached or fetched data, or rejects with the fetch - * error. - * @deprecated Use queryClient.query(options) instead. This method will be removed in the next major version. + * Fetches and caches a query, or returns its cached data if it isn't stale. + * Unlike in observers, the fetch isn't retried unless `retry` is set. + * + * @deprecated Use queryClient.query(options) instead. This method will be + * removed in the next major version. + * @param options - The query options, including the `queryKey` and the + * `queryFn` used if the query needs to fetch. + * @returns A promise that resolves to the cached or fetched data, or rejects + * with the fetch error. */ override fetchQuery< TQueryFnData, @@ -357,7 +370,9 @@ export class QueryClient extends QC { ): Promise /** * {@inheritDoc QueryClient.fetchQuery:0} - * @deprecated Use queryClient.query(options) instead. This method will be removed in the next major version. + * + * @deprecated Use queryClient.query(options) instead. This method will be + * removed in the next major version. */ override fetchQuery< TQueryFnData, @@ -394,12 +409,15 @@ export class QueryClient extends QC { } /** - * Fetches and caches a query like {@link QueryClient#fetchQuery}, but ignores the result and any - * error. - * @param options - The query options, including the `queryKey` and the `queryFn` used if the - * query needs to fetch. + * Fetches and caches a query like {@link QueryClient#fetchQuery}, but ignores + * the result and any error. + * + * @deprecated Use queryClient.query(options) instead. You can swallow errors + * with `.catch(noop)`. This method will be removed in the next major + * version. + * @param options - The query options, including the `queryKey` and the + * `queryFn` used if the query needs to fetch. * @returns A promise that resolves once the fetch settles. It never rejects. - * @deprecated Use queryClient.query(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. */ override prefetchQuery< TQueryFnData = unknown, @@ -411,7 +429,10 @@ export class QueryClient extends QC { ): Promise /** * {@inheritDoc QueryClient.prefetchQuery:0} - * @deprecated Use queryClient.query(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. + * + * @deprecated Use queryClient.query(options) instead. You can swallow errors + * with `.catch(noop)`. This method will be removed in the next major + * version. */ override prefetchQuery< TQueryFnData = unknown, @@ -505,12 +526,15 @@ export class QueryClient extends QC { } /** - * Fetches and caches an infinite query, or returns its cached data if it isn't stale. - * @param options - The infinite query options, including the `queryKey`, the `queryFn`, and the - * `initialPageParam`. - * @returns A promise that resolves to the cached or fetched {@link InfiniteData}, or rejects with - * the fetch error. - * @deprecated Use queryClient.infiniteQuery(options) instead. This method will be removed in the next major version. + * Fetches and caches an infinite query, or returns its cached data if it + * isn't stale. + * + * @deprecated Use queryClient.infiniteQuery(options) instead. This method + * will be removed in the next major version. + * @param options - The infinite query options, including the `queryKey`, the + * `queryFn`, and the `initialPageParam`. + * @returns A promise that resolves to the cached or fetched + * {@link InfiniteData}, or rejects with the fetch error. */ override fetchInfiniteQuery< TQueryFnData = unknown, @@ -529,7 +553,9 @@ export class QueryClient extends QC { ): Promise> /** * {@inheritDoc QueryClient.fetchInfiniteQuery:0} - * @deprecated Use queryClient.infiniteQuery(options) instead. This method will be removed in the next major version. + * + * @deprecated Use queryClient.infiniteQuery(options) instead. This method + * will be removed in the next major version. */ override fetchInfiniteQuery< TQueryFnData, @@ -570,12 +596,16 @@ export class QueryClient extends QC { } /** - * Fetches and caches an infinite query like {@link QueryClient#fetchInfiniteQuery}, but ignores - * the result and any error. - * @param options - The infinite query options, including the `queryKey`, the `queryFn`, and the - * `initialPageParam`. + * Fetches and caches an infinite query like + * {@link QueryClient#fetchInfiniteQuery}, but ignores the result and any + * error. + * + * @deprecated use void queryClient.infiniteQuery(options) instead. You can + * swallow errors with `.catch(noop)`. This method will be removed in the + * next major version. + * @param options - The infinite query options, including the `queryKey`, the + * `queryFn`, and the `initialPageParam`. * @returns A promise that resolves once the fetch settles. It never rejects. - * @deprecated use void queryClient.infiniteQuery(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. */ override prefetchInfiniteQuery< TQueryFnData, @@ -594,7 +624,10 @@ export class QueryClient extends QC { ): Promise /** * {@inheritDoc QueryClient.prefetchInfiniteQuery:0} - * @deprecated use void queryClient.infiniteQuery(options) instead. You can swallow errors with `.catch(noop)`. This method will be removed in the next major version. + * + * @deprecated use void queryClient.infiniteQuery(options) instead. You can + * swallow errors with `.catch(noop)`. This method will be removed in the + * next major version. */ override prefetchInfiniteQuery< TQueryFnData, diff --git a/packages/vue-query/src/queryOptions.ts b/packages/vue-query/src/queryOptions.ts index bda81fb2cac..51b037222c8 100644 --- a/packages/vue-query/src/queryOptions.ts +++ b/packages/vue-query/src/queryOptions.ts @@ -16,14 +16,17 @@ import type { } from '@tanstack/query-core' /** - * The plain, unwrapped options that `queryOptions` hands back, and what `useQuery`, `useQueries`, and the - * `queryClient` methods see once `ref`s have been resolved. To pass options in, use - * {@link UseQueryOptions}, which accepts the same options as `ref`s and `computed`s too. + * The plain, unwrapped options that `queryOptions` hands back, and what + * `useQuery`, `useQueries`, and the `queryClient` methods see once `ref`s have + * been resolved. To pass options in, use {@link UseQueryOptions}, which accepts + * the same options as `ref`s and `computed`s too. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. - * @template TQueryData - The type of data stored in the cache, before `select` runs. Defaults to - * `TQueryFnData` and can be configured independently of it. + * @template TQueryData - The type of data stored in the cache, before `select` + * runs. Defaults to `TQueryFnData` and can be configured independently of + * it. * @template TQueryKey - The type of your `queryKey`. */ export type QueryOptions< @@ -65,27 +68,34 @@ export type QueryOptions< type SkipTokenForUseQuery = symbol /** - * The options accepted by `queryOptions`, `useQuery`, and the other query hooks. `enabled` tracks reactive - * dependencies automatically as a `ref`, a plain value, or a reactive getter (`() => ...`). `queryKey` reacts - * through a `ref` or a reactive getter for the array itself, or `ref`s and reactive getters as individual - * entries. Other options are read once when passed as a plain value, and stay reactive when passed as a `ref` - * or a `computed`. Only `enabled` and `queryKey` read a function as a getter, so `queryFn` reacts through a - * `computed`: a function there is the query function itself. + * The options accepted by `queryOptions`, `useQuery`, and the other query + * hooks. `enabled` tracks reactive dependencies automatically as a `ref`, a + * plain value, or a reactive getter (`() => ...`). `queryKey` reacts through a + * `ref` or a reactive getter for the array itself, or `ref`s and reactive + * getters as individual entries. Other options are read once when passed as a + * plain value, and stay reactive when passed as a `ref` or a `computed`. Only + * `enabled` and `queryKey` read a function as a getter, so `queryFn` reacts + * through a `computed`: a function there is the query function itself. * - * If you instead pass a getter for the whole options object (`useQuery(() => ({ ... }))`), every option - * inside it — including `staleTime`, `retry`, and `select` — is re-evaluated whenever the getter's own - * reactive dependencies change, since the entire object is recomputed. + * If you instead pass a getter for the whole options object (`useQuery(() => ({ + * ... }))`), every option inside it — including `staleTime`, `retry`, and + * `select` — is re-evaluated whenever the getter's own reactive dependencies + * change, since the entire object is recomputed. * - * `select` only re-runs when `data` changes, or when the `select` function's own reference changes. Since a - * Vue `setup()` function runs only once per component instance, an inline `select` function passed directly - * to `queryOptions`/`useQuery` already has a stable reference across reactive updates. An inline `select` - * created inside a whole-options getter is recreated — and so can change reference — every time that getter + * `select` only re-runs when `data` changes, or when the `select` function's + * own reference changes. Since a Vue `setup()` function runs only once per + * component instance, an inline `select` function passed directly to + * `queryOptions`/`useQuery` already has a stable reference across reactive + * updates. An inline `select` created inside a whole-options getter is + * recreated — and so can change reference — every time that getter * re-evaluates. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. - * @template TQueryData - The type of data stored in the cache, before `select` runs. Defaults to - * `TQueryFnData` and can be configured independently of it. + * @template TQueryData - The type of data stored in the cache, before `select` + * runs. Defaults to `TQueryFnData` and can be configured independently of + * it. * @template TQueryKey - The type of your `queryKey`. */ export type UseQueryOptions< @@ -137,11 +147,14 @@ export type UseQueryOptions< type WithUndefinedInitialData = { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. Unlike `queryKey`/`enabled`, this is not reactive — it isn't re-evaluated on `ref` changes. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. Unlike + * `queryKey`/`enabled`, this is not reactive — it isn't re-evaluated on `ref` + * changes. */ initialData?: | undefined @@ -151,11 +164,14 @@ type WithUndefinedInitialData = { type WithDefinedInitialData = { /** - * If set, this value will be used as the initial data for the query cache (as long as the query hasn't been - * created or cached yet). If set to a function, the function will be called **once** during the shared/root - * query initialization, and be expected to synchronously return the initial data. Initial data is - * considered stale by default unless a `staleTime` has been set. `initialData` **is persisted** to the - * cache. Unlike `queryKey`/`enabled`, this is not reactive — it isn't re-evaluated on `ref` changes. + * If set, this value will be used as the initial data for the query cache (as + * long as the query hasn't been created or cached yet). If set to a function, + * the function will be called **once** during the shared/root query + * initialization, and be expected to synchronously return the initial data. + * Initial data is considered stale by default unless a `staleTime` has been + * set. `initialData` **is persisted** to the cache. Unlike + * `queryKey`/`enabled`, this is not reactive — it isn't re-evaluated on `ref` + * changes. */ initialData: | NonUndefinedGuard @@ -163,8 +179,10 @@ type WithDefinedInitialData = { } /** - * The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be - * `undefined` while the query is `pending`. + * The options accepted by the `queryOptions` overload selected when no + * `initialData` is set — `data` may be `undefined` while the query is + * `pending`. + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -179,8 +197,10 @@ export type UndefinedInitialQueryOptions< WithUndefinedInitialData /** - * The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never - * `undefined` (unless a `select` changes `TData` to include `undefined`). + * The options accepted by the `queryOptions` overload selected when + * `initialData` is set — `data` is never `undefined` (unless a `select` changes + * `TData` to include `undefined`). + * * @template TQueryFnData - The type your `queryFn` resolves to. * @template TError - The type of errors your `queryFn` may throw. * @template TData - The type `data` ends up as after `select` runs. @@ -195,8 +215,9 @@ export type DefinedInitialQueryOptions< WithDefinedInitialData /** - * The options returned by the `queryOptions` overload selected when `initialData` is omitted or may be - * `undefined`, with the `queryKey` tagged with the query's data and error types. + * The options returned by the `queryOptions` overload selected when + * `initialData` is omitted or may be `undefined`, with the `queryKey` tagged + * with the query's data and error types. */ export type UndefinedInitialQueryOptionsWithDataTag< TQueryFnData = unknown, @@ -208,8 +229,9 @@ export type UndefinedInitialQueryOptionsWithDataTag< QueryKeyWithDataTag /** - * The options returned by the `queryOptions` overload selected when `initialData` is set, with the - * `queryKey` tagged with the query's data and error types. + * The options returned by the `queryOptions` overload selected when + * `initialData` is set, with the `queryKey` tagged with the query's data and + * error types. */ export type DefinedInitialQueryOptionsWithDataTag< TQueryFnData = unknown, @@ -221,32 +243,37 @@ export type DefinedInitialQueryOptionsWithDataTag< QueryKeyWithDataTag /** - * You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can - * be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and - * is the query key to generate options for. + * You can generally pass everything to `queryOptions` that you can also pass to + * `useQuery`. These options can be shared across hooks and imperative APIs such + * as `queryClient.query`. `options.queryKey` is required and is the query key + * to generate options for. + * + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * @param options - The {@link DefinedInitialQueryOptions} to use — everything you can pass to `useQuery`, with - * `initialData` set. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link useQuery} to run a query with these options. * @example - * ```vue - * + * ``` * - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery(postsOptions) - * - * ``` + * @param options - The {@link DefinedInitialQueryOptions} to use — everything + * you can pass to `useQuery`, with `initialData` set. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, @@ -258,30 +285,34 @@ export function queryOptions< ): DefinedInitialQueryOptionsWithDataTag /** - * Same as the plain-object overload, but for options that close over reactive state (`ref`s read inside the - * function body). Wrap them in a getter so `queryClient` methods like `invalidateQueries`/`fetchQuery` always - * read the current values instead of the ones captured when the options were created. - * @param options - A function returning the {@link DefinedInitialQueryOptions} to use, re-evaluated on demand. - * @returns A function that returns the same options object, typed so that `queryKey` carries the inferred data - * type. - * @see {@link useQuery} to run a query with these options. + * Same as the plain-object overload, but for options that close over reactive + * state (`ref`s read inside the function body). Wrap them in a getter so + * `queryClient` methods like `invalidateQueries`/`fetchQuery` always read the + * current values instead of the ones captured when the options were created. + * * @example - * ```vue - * - * ``` + * // Pass the getter itself, not `postOptions()`, so the query keeps reacting to `postId` changes. + * const { data } = useQuery(postOptions) + * + * ``` + * + * @param options - A function returning the {@link DefinedInitialQueryOptions} + * to use, re-evaluated on demand. + * @returns A function that returns the same options object, typed so that + * `queryKey` carries the inferred data type. + * @see {@link useQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, @@ -303,28 +334,33 @@ export function queryOptions< > /** - * You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can - * be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and - * is the query key to generate options for. - * @param options - The {@link UndefinedInitialQueryOptions} to use — everything you can pass to `useQuery`. - * @returns The same options object, typed so that `queryKey` carries the inferred data type. - * @see {@link useQuery} to run a query with these options. + * You can generally pass everything to `queryOptions` that you can also pass to + * `useQuery`. These options can be shared across hooks and imperative APIs such + * as `queryClient.query`. `options.queryKey` is required and is the query key + * to generate options for. + * * @example - * A parameterized factory, so the same options object can be reused per `id`: - * ```vue - * + * ``` * - * const { data, isPending, isError, error } = useQuery(postOptions('1')) - * - * ``` + * @param options - The {@link UndefinedInitialQueryOptions} to use — everything + * you can pass to `useQuery`. + * @returns The same options object, typed so that `queryKey` carries the + * inferred data type. + * @see {@link useQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, @@ -341,53 +377,58 @@ export function queryOptions< > /** - * Same as the plain-object overload, but for options that close over reactive state (`ref`s read inside the - * function body). Wrap them in a getter so the `queryKey` — and anything else derived from a `ref` — reacts - * to changes, and so `queryClient` methods like `invalidateQueries`/`fetchQuery` always read the current - * values instead of the ones captured when the options were created. - * @param options - A function returning the {@link UndefinedInitialQueryOptions} to use, re-evaluated on - * demand. - * @returns A function that returns the same options object, typed so that `queryKey` carries the inferred - * data type. - * @see {@link useQuery} to run a query with these options. + * Same as the plain-object overload, but for options that close over reactive + * state (`ref`s read inside the function body). Wrap them in a getter so the + * `queryKey` — and anything else derived from a `ref` — reacts to changes, and + * so `queryClient` methods like `invalidateQueries`/`fetchQuery` always read + * the current values instead of the ones captured when the options were + * created. + * * @example - * ```vue - * + * ``` * - * // Pass the getter itself, not `postOptions()`, so the query keeps reacting to `postId` changes. - * const { data } = useQuery(postOptions) - * const queryClient = useQueryClient() - * // Here, call `postOptions()` so `invalidateQueries` reads the current `queryKey` right away. - * queryClient.invalidateQueries(postOptions()) - * - * ``` * @example - * A parameterized factory that disables the query, type safe, until `postId` is set. The whole-options getter - * re-evaluates `queryFn` on every change to `postId`. `queryFn` can also be a `computed`, but never a bare - * getter, since a function there is the query function itself: - * ```vue - * + * ``` * - * const props = defineProps<{ postId: number | undefined }>() - * const { data, isLoading, isError, error } = useQuery(postOptions(props.postId)) - * - * ``` + * @param options - A function returning the + * {@link UndefinedInitialQueryOptions} to use, re-evaluated on demand. + * @returns A function that returns the same options object, typed so that + * `queryKey` carries the inferred data type. + * @see {@link useQuery} to run a query with these options. */ export function queryOptions< TQueryFnData = unknown, diff --git a/packages/vue-query/src/types.ts b/packages/vue-query/src/types.ts index 23b7dacbba0..e80b8690650 100644 --- a/packages/vue-query/src/types.ts +++ b/packages/vue-query/src/types.ts @@ -26,22 +26,25 @@ type UnwrapLeaf = export type MaybeGetter = T | (() => T) /** - * A plain value, a `Ref`, or a `ComputedRef`. Accepting this instead of a bare `T` lets a composable take - * either a reactive or a static value for a given option — see the [Reactivity guide](../../reactivity.md). + * A plain value, a `Ref`, or a `ComputedRef`. Accepting this instead of a bare + * `T` lets a composable take either a reactive or a static value for a given + * option — see the [Reactivity guide](../../reactivity.md). */ export type MaybeRef = Ref | ComputedRef | T /** - * A {@link MaybeRef}, or a reactive getter (`() => T`). Reactive getters are a lighter-weight alternative to - * `computed` for deriving a value from other reactive state — see the - * [Reactivity guide](../../reactivity.md#using-derived-state-inside-queries). + * A {@link MaybeRef}, or a reactive getter (`() => T`). Reactive getters are a + * lighter-weight alternative to `computed` for deriving a value from other + * reactive state — see the [Reactivity + * guide](../../reactivity.md#using-derived-state-inside-queries). */ export type MaybeRefOrGetter = MaybeRef | (() => T) /** - * Like {@link MaybeRef}, but applied recursively to every property of `T` — so each field of an options object - * (for example, an entry inside a `queryKey` array) can independently be a plain value or a `ref`, not just the - * object as a whole. + * Like {@link MaybeRef}, but applied recursively to every property of `T` — so + * each field of an options object (for example, an entry inside a `queryKey` + * array) can independently be a plain value or a `ref`, not just the object as + * a whole. */ export type MaybeRefDeep = MaybeRef< T extends Function @@ -54,13 +57,16 @@ export type MaybeRefDeep = MaybeRef< > /** - * Rejects `unknown`, collapsing it to `never` — used to keep generic inference from silently widening. + * Rejects `unknown`, collapsing it to `never` — used to keep generic inference + * from silently widening. + * * @internal */ export type NoUnknown = Equal extends true ? never : T /** * Type-level equality check between `TTargetA` and `TTargetB`. + * * @internal */ export type Equal = @@ -70,7 +76,10 @@ export type Equal = ? true : false -/** The inverse of {@link MaybeRefDeep} — recursively unwraps any `Ref`s in `T` back to their plain value types. */ +/** + * The inverse of {@link MaybeRefDeep} — recursively unwraps any `Ref`s in `T` + * back to their plain value types. + */ export type DeepUnwrapRef = T extends UnwrapLeaf ? T : T extends Ref @@ -82,18 +91,22 @@ export type DeepUnwrapRef = T extends UnwrapLeaf : UnwrapRef /** - * The `vue-query`-specific `shallow` option, accepted by query and mutation options. + * The `vue-query`-specific `shallow` option, accepted by query and mutation + * options. */ export type ShallowOption = { /** - * Return data in a shallow ref object (it is `false` by default). It can be set to `true` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive. + * Return data in a shallow ref object (it is `false` by default). It can be + * set to `true` to return data in a shallow ref object, which can improve + * performance if your data does not need to be deeply reactive. */ shallow?: boolean } /** - * The options of a mutation. Same as {@link MutationObserverOptions} from `@tanstack/query-core`, minus the - * internal `_defaulted` flag, plus the `shallow` option. + * The options of a mutation. Same as {@link MutationObserverOptions} from + * `@tanstack/query-core`, minus the internal `_defaulted` flag, plus the + * `shallow` option. */ export type MutationOptions< TData = unknown, @@ -107,48 +120,44 @@ export type MutationOptions< ShallowOption /** - * The default options of a `QueryClient`, applied to every query (`queries`), mutation - * (`mutations`), `hydrate`, and `dehydrate` call unless overridden. Query and mutation defaults also - * accept the `shallow` option. + * The default options of a `QueryClient`, applied to every query (`queries`), + * mutation (`mutations`), `hydrate`, and `dehydrate` call unless overridden. + * Query and mutation defaults also accept the `shallow` option. */ export interface DefaultOptions { /** - * Default options applied to every query, unless overridden per-query. Also accepts the - * `shallow` option. + * Default options applied to every query, unless overridden per-query. Also + * accepts the `shallow` option. */ queries?: OmitKeyof, 'queryKey'> & ShallowOption /** - * Default options applied to every mutation, unless overridden per-mutation. Also accepts the - * `shallow` option. + * Default options applied to every mutation, unless overridden per-mutation. + * Also accepts the `shallow` option. */ mutations?: MutationObserverOptions & ShallowOption /** - * Default options used when hydrating queries and mutations; see {@link HydrateOptions}. + * Default options used when hydrating queries and mutations; see + * {@link HydrateOptions}. */ hydrate?: HydrateOptions['defaultOptions'] /** - * Default options used when dehydrating the client's caches; see {@link DehydrateOptions}. + * Default options used when dehydrating the client's caches; see + * {@link DehydrateOptions}. */ dehydrate?: DehydrateOptions } /** - * The options of `new QueryClient()`: the `queryCache` and `mutationCache` to use, and the - * `defaultOptions` for its queries and mutations. + * The options of `new QueryClient()`: the `queryCache` and `mutationCache` to + * use, and the `defaultOptions` for its queries and mutations. */ export interface QueryClientConfig { - /** - * The `QueryCache` to use. A new one is created if omitted. - */ + /** The `QueryCache` to use. A new one is created if omitted. */ queryCache?: QueryCache - /** - * The `MutationCache` to use. A new one is created if omitted. - */ + /** The `MutationCache` to use. A new one is created if omitted. */ mutationCache?: MutationCache - /** - * The default options of the queries and mutations of this `QueryClient`. - */ + /** The default options of the queries and mutations of this `QueryClient`. */ defaultOptions?: DefaultOptions } diff --git a/packages/vue-query/src/useBaseQuery.ts b/packages/vue-query/src/useBaseQuery.ts index c8051c8d1c3..4a0309ab663 100644 --- a/packages/vue-query/src/useBaseQuery.ts +++ b/packages/vue-query/src/useBaseQuery.ts @@ -25,8 +25,9 @@ import type { UseInfiniteQueryOptions } from './useInfiniteQuery' import type { MaybeRefOrGetter } from './types' /** - * The result of the query composables: every property of the observer result wrapped in a `Ref`, except - * the `refetch`, `fetchNextPage`, and `fetchPreviousPage` functions, plus `suspense`. + * The result of the query composables: every property of the observer result + * wrapped in a `Ref`, except the `refetch`, `fetchNextPage`, and + * `fetchPreviousPage` functions, plus `suspense`. */ export type UseBaseQueryReturnType< TData, @@ -41,12 +42,14 @@ export type UseBaseQueryReturnType< : Ref[K]> } & { /** - * Returns a promise for use with Vue's `Suspense` or `onServerPrefetch`. It fetches the query if it has no - * data or its data is stale and resolves with the result once that fetch resolves (usually when the query - * function finishes, but earlier after the first chunk of a streamed query or when data is set during the - * fetch), or resolves immediately if the data is fresh. While the query is disabled, it waits until the query - * is enabled. If the fetch fails, it resolves with the error result, unless `throwOnError` is (or returns) - * `true`, in which case it rejects. + * Returns a promise for use with Vue's `Suspense` or `onServerPrefetch`. It + * fetches the query if it has no data or its data is stale and resolves with + * the result once that fetch resolves (usually when the query function + * finishes, but earlier after the first chunk of a streamed query or when + * data is set during the fetch), or resolves immediately if the data is + * fresh. While the query is disabled, it waits until the query is enabled. If + * the fetch fails, it resolves with the error result, unless `throwOnError` + * is (or returns) `true`, in which case it rejects. */ suspense: () => Promise } @@ -64,10 +67,13 @@ type UseQueryOptionsGeneric< /** * Base implementation shared by `useQuery` and `useInfiniteQuery`. - * @param Observer - The observer class from query-core (`QueryObserver` or `InfiniteQueryObserver`). - * @param options - A `ref`, plain value, or reactive getter resolving to the query options. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. + * + * @param Observer - The observer class from query-core (`QueryObserver` or + * `InfiniteQueryObserver`). + * @param options - A `ref`, plain value, or reactive getter resolving to the + * query options. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. * @returns The query result as `ref`s, plus the `suspense` function. */ export function useBaseQuery< diff --git a/packages/vue-query/src/useInfiniteQuery.ts b/packages/vue-query/src/useInfiniteQuery.ts index 53f735a376e..fe8af85fcb8 100644 --- a/packages/vue-query/src/useInfiniteQuery.ts +++ b/packages/vue-query/src/useInfiniteQuery.ts @@ -25,8 +25,9 @@ import type { import type { QueryClient } from './queryClient' /** - * The options accepted by `useInfiniteQuery`. Same as {@link InfiniteQueryObserverOptions} from - * `@tanstack/query-core`, plus the `shallow` option. Each option except `shallow` can also be a `ref` (and + * The options accepted by `useInfiniteQuery`. Same as + * {@link InfiniteQueryObserverOptions} from `@tanstack/query-core`, plus the + * `shallow` option. Each option except `shallow` can also be a `ref` (and * `enabled` a reactive getter). */ export type UseInfiniteQueryOptions< @@ -68,8 +69,9 @@ export type UseInfiniteQueryOptions< > /** - * The result of `useInfiniteQuery`: {@link InfiniteQueryObserverResult} from `@tanstack/query-core`, with - * its properties wrapped in `Ref`s as in {@link UseBaseQueryReturnType}. + * The result of `useInfiniteQuery`: {@link InfiniteQueryObserverResult} from + * `@tanstack/query-core`, with its properties wrapped in `Ref`s as in + * {@link UseBaseQueryReturnType}. */ export type UseInfiniteQueryReturnType = UseBaseQueryReturnType< TData, @@ -78,51 +80,59 @@ export type UseInfiniteQueryReturnType = UseBaseQueryReturnType< > /** - * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. + * The options for `useInfiniteQuery` are identical to `useQuery`, with the + * addition of `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, + * and `maxPages`. * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). * - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` for the array itself, or `ref`s and reactive getters as - * individual entries — the array itself can't be a bare getter. - * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `useInfiniteQuery`, with `initialData` set. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.value.pages` and - * `data.value.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage && !isFetching`. + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * for the array itself, or `ref`s and reactive getters as individual entries — + * the array itself can't be a bare getter. + * + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage && !isFetching`. * @example - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - The {@link DefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`, with `initialData` set. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.value.pages` and + * `data.value.pageParams` are also added, as long as a `select` doesn't + * change `TData` away from its default `InfiniteData` shape. */ export function useInfiniteQuery< TQueryFnData, @@ -144,30 +154,27 @@ export function useInfiniteQuery< ): UseInfiniteQueryReturnType /** - * The options for `useInfiniteQuery` are identical to `useQuery`, with the addition of - * `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, and `maxPages`. + * The options for `useInfiniteQuery` are identical to `useQuery`, with the + * addition of `initialPageParam`, `getNextPageParam`, `getPreviousPageParam`, + * and `maxPages`. + * + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * for the array itself, or `ref`s and reactive getters as individual entries — + * the array itself can't be a bare getter. * - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` for the array itself, or `ref`s and reactive getters as - * individual entries — the array itself can't be a bare getter. - * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — everything you can pass to - * `useInfiniteQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.value.pages` and - * `data.value.pageParams` are also added, as long as a `select` doesn't change `TData` away from its default - * `InfiniteData` shape. - * @remarks Keep in mind that imperative fetch calls, such as `fetchNextPage`, may interfere with the default - * refetch behavior, resulting in outdated data. Make sure to call these functions only in response to user - * actions, or add conditions like `hasNextPage && !isFetching`. + * @remarks + * Keep in mind that imperative fetch calls, such as `fetchNextPage`, may + * interfere with the default refetch behavior, resulting in outdated data. + * Make sure to call these functions only in response to user actions, or add + * conditions like `hasNextPage && !isFetching`. * @example - * Fetching the next page from a "Load More" button click: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Fetching the next page automatically as the user scrolls, using an `IntersectionObserver` on a - * sentinel element after the list: - * ```vue - * + * onUnmounted(() => observer?.disconnect()) + * * - * - * ``` + * ``` + * + * @param options - The {@link UndefinedInitialDataInfiniteOptions} to use — + * everything you can pass to `useInfiniteQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. `data.value.pages` and + * `data.value.pageParams` are also added, as long as a `select` doesn't + * change `TData` away from its default `InfiniteData` shape. */ export function useInfiniteQuery< TQueryFnData, @@ -275,78 +293,85 @@ export function useInfiniteQuery< ): UseInfiniteQueryReturnType /** - * Fallback overload for options whose `initialData` presence isn't statically known — for example, a - * `ref`/reactive object built up conditionally, rather than a plain object literal. Prefer one of the other - * overloads when possible, since they infer whether `data` can be `undefined` from `initialData` directly. + * Fallback overload for options whose `initialData` presence isn't statically + * known — for example, a `ref`/reactive object built up conditionally, rather + * than a plain object literal. Prefer one of the other overloads when possible, + * since they infer whether `data` can be `undefined` from `initialData` + * directly. + * + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * for the array itself, or `ref`s and reactive getters as individual entries — + * the array itself can't be a bare getter. * - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` for the array itself, or `ref`s and reactive getters as - * individual entries — the array itself can't be a bare getter. - * @param options - A `ref`, plain value, or reactive getter resolving to the {@link UseInfiniteQueryOptions} to - * use. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The same properties as `useQuery`, with the addition of `fetchNextPage`, `fetchPreviousPage`, - * `hasNextPage`, `hasPreviousPage`, `isFetchingNextPage`, and `isFetchingPreviousPage`. * @example - * Passing a whole-options getter so `maxPages` reacts to a setting stored elsewhere, not just `queryKey`: - * ```vue - * + * })) + * * - * - * ``` + * ``` + * * @example - * A query that's disabled, type-safe, until `postId` is set — pass `skipToken` as `queryFn` instead of - * setting `enabled: false`. This requires a whole-options getter: `queryFn` isn't itself reactive, so the - * getter is what re-evaluates it on every change to `props.postId`: - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - A `ref`, plain value, or reactive getter resolving to the + * {@link UseInfiniteQueryOptions} to use. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The same properties as `useQuery`, with the addition of + * `fetchNextPage`, `fetchPreviousPage`, `hasNextPage`, `hasPreviousPage`, + * `isFetchingNextPage`, and `isFetchingPreviousPage`. */ export function useInfiniteQuery< TQueryFnData, diff --git a/packages/vue-query/src/useIsFetching.ts b/packages/vue-query/src/useIsFetching.ts index 99a190767fc..7bd6cc04320 100644 --- a/packages/vue-query/src/useIsFetching.ts +++ b/packages/vue-query/src/useIsFetching.ts @@ -7,50 +7,56 @@ import type { MaybeRefDeep } from './types' import type { QueryClient } from './queryClient' /** - * The filters accepted by `useIsFetching`: {@link QueryFilters} as a plain object, a `ref`, or a reactive - * getter. + * The filters accepted by `useIsFetching`: {@link QueryFilters} as a plain + * object, a `ref`, or a reactive getter. */ export type UseIsFetchingFilters = | MaybeRefDeep | (() => MaybeRefDeep) /** - * The `useIsFetching` composable returns a `ref` to the `number` of the queries that your application is - * loading or fetching in the background (useful for app-wide loading indicators). + * The `useIsFetching` composable returns a `ref` to the `number` of the queries + * that your application is loading or fetching in the background (useful for + * app-wide loading indicators). + * + * `fetchingFilters` may be a plain object, `MaybeRefDeep`, or a reactive getter + * (`() => ({ ... })`) — pass a getter if the filters themselves depend on other + * reactive state. * - * `fetchingFilters` may be a plain object, `MaybeRefDeep`, or a reactive getter (`() => ({ ... })`) — pass a - * getter if the filters themselves depend on other reactive state. - * @param fetchingFilters - The {@link QueryFilters} to narrow down the matched queries. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns A `ref` to the `number` of the queries that your application is currently loading or fetching in - * the background. * @example - * ```vue - * + * // How many queries matching the posts prefix are fetching? + * const isFetchingPosts = useIsFetching({ queryKey: ['posts'] }) + * * - * + * ``` + * * @example - * A global loading indicator for any query fetching in the background, not just the ones on screen: - * ```vue - * + * const isFetching = useIsFetching() + * * - * + * ``` + * + * @param fetchingFilters - The {@link QueryFilters} to narrow down the matched + * queries. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns A `ref` to the `number` of the queries that your application is + * currently loading or fetching in the background. */ export function useIsFetching( fetchingFilters: UseIsFetchingFilters = {}, diff --git a/packages/vue-query/src/useMutation.ts b/packages/vue-query/src/useMutation.ts index 799b321ba4d..641b46abd8a 100644 --- a/packages/vue-query/src/useMutation.ts +++ b/packages/vue-query/src/useMutation.ts @@ -23,8 +23,8 @@ import type { MaybeRefDeep, MutationOptions } from './types' import type { QueryClient } from './queryClient' /** - * The {@link MutationObserverResult} properties without `mutate` and `reset`, which `useMutation` replaces with - * its own versions. + * The {@link MutationObserverResult} properties without `mutate` and `reset`, + * which `useMutation` replaces with its own versions. */ export type MutationResult = DistributiveOmit< @@ -33,8 +33,8 @@ export type MutationResult = > /** - * The options accepted by `useMutation`: {@link MutationOptions} as a plain object, a `ref`, or a reactive - * getter. + * The options accepted by `useMutation`: {@link MutationOptions} as a plain + * object, a `ref`, or a reactive getter. */ export type UseMutationOptions< TData = unknown, @@ -59,8 +59,9 @@ type MutateSyncFunction< ) => void /** - * The result of `useMutation`: the {@link MutationObserverResult} properties wrapped in `Ref`s, plus the - * fire-and-forget `mutate`, the awaitable `mutateAsync`, and `reset`. + * The result of `useMutation`: the {@link MutationObserverResult} properties + * wrapped in `Ref`s, plus the fire-and-forget `mutate`, the awaitable + * `mutateAsync`, and `reset`. */ export type UseMutationReturnType< TData, @@ -80,159 +81,169 @@ export type UseMutationReturnType< } /** - * Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. - * `useMutation` is the composable for that. + * Unlike queries, mutations are typically used to create/update/delete data or + * perform server side-effects. `useMutation` is the composable for that. + * + * `options` may be a plain object, a `ref`, or a reactive getter (`() => ({ ... + * })`) — pass a getter if the options themselves depend on other reactive + * state. * - * `options` may be a plain object, a `ref`, or a reactive getter (`() => ({ ... })`) — pass a getter - * if the options themselves depend on other reactive state. - * @param options - The {@link UseMutationOptions} to use — everything you can pass to `useMutation`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns `mutate`/`mutateAsync` also accept per-call `onSuccess`/`onError`/`onSettled` callbacks as a second - * argument, useful for triggering call-site side effects (e.g. navigation) without coupling them to the shared - * mutation definition. Hook-level callbacks (passed to `options`) fire for every mutation; per-call - * callbacks fire only for the latest call you've made. - * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites, or to look - * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). * @example - * ```vue - * + * } + * * - * + * ``` + * * @example - * Rendering the mutation's own state, rather than just firing it off: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Optimistic update via `onMutate`, rolling back on `onError`: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Callbacks passed per call to `mutate` only fire for the last call — `mutateAsync` gives you a - * promise per call instead, so you can wait for all of them when they succeed: - * ```vue - * + * * - * + * ``` + * * @example - * If some of the mutations above can fail independently of the others, and you want to know which ones - * did — rather than losing that information the moment the first one rejects — swap `Promise.all` for - * `Promise.allSettled`: - * ```vue - * + * } + * * - * + * ``` + * + * @param options - The {@link UseMutationOptions} to use — everything you can + * pass to `useMutation`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns `mutate`/`mutateAsync` also accept per-call + * `onSuccess`/`onError`/`onSettled` callbacks as a second argument, useful + * for triggering call-site side effects (e.g. navigation) without coupling + * them to the shared mutation definition. Hook-level callbacks (passed to + * `options`) fire for every mutation; per-call callbacks fire only for the + * latest call you've made. + * @see {@link mutationOptions} to share these options across multiple `useMutation` call sites, or to look + * the mutation up elsewhere via its `mutationKey` (e.g. with `useMutationState`). */ export function useMutation< TData = unknown, diff --git a/packages/vue-query/src/useMutationState.ts b/packages/vue-query/src/useMutationState.ts index 4d29f2628d9..d1b27325b66 100644 --- a/packages/vue-query/src/useMutationState.ts +++ b/packages/vue-query/src/useMutationState.ts @@ -21,36 +21,42 @@ import type { MutationCache } from './mutationCache' type VueMutationFilters = MaybeRefDeep /** - * The filters accepted by `useIsMutating`: {@link MutationFilters} as a plain object, a `ref`, or a reactive - * getter. + * The filters accepted by `useIsMutating`: {@link MutationFilters} as a plain + * object, a `ref`, or a reactive getter. */ export type UseIsMutatingFilters = | VueMutationFilters | (() => VueMutationFilters) /** - * The `useIsMutating` composable returns a `ref` to the `number` of mutations that your application currently - * has `pending` (useful for app-wide loading indicators). - * - * `filters` may be a plain object, `MaybeRefDeep`, or a reactive getter (`() => ({ ... })`) — pass a getter if - * the filters themselves depend on other reactive state. - * @param filters - The {@link MutationFilters} to narrow down the matched mutations. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns A `ref` to the `number` of the mutations that your application currently has `pending`. + * The `useIsMutating` composable returns a `ref` to the `number` of mutations + * that your application currently has `pending` (useful for app-wide loading + * indicators). + * + * `filters` may be a plain object, `MaybeRefDeep`, or a reactive getter (`() => + * ({ ... })`) — pass a getter if the filters themselves depend on other + * reactive state. + * * @example - * ```vue - * + * // How many mutations matching the posts prefix are in progress? + * const isMutatingPosts = useIsMutating({ mutationKey: ['posts'] }) + * * - * + * ``` + * + * @param filters - The {@link MutationFilters} to narrow down the matched + * mutations. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns A `ref` to the `number` of the mutations that your application + * currently has `pending`. */ export function useIsMutating( filters: UseIsMutatingFilters = {}, @@ -92,29 +98,30 @@ type MutationTypeFromResult = [TResult] extends [ : Mutation /** - * The options accepted by `useMutationState`: the `filters` matching the mutations, and `select` to map each - * one (to its state, by default). + * The options accepted by `useMutationState`: the `filters` matching the + * mutations, and `select` to map each one (to its state, by default). */ export type MutationStateOptions< TResult = MutationState, TMutation extends Mutation = MutationTypeFromResult, > = { - /** - * The filters that select the mutations to return the state of. - */ + /** The filters that select the mutations to return the state of. */ filters?: VueMutationFilters /** - * Maps each matching mutation to the value returned for it. Defaults to the mutation's `state`. + * Maps each matching mutation to the value returned for it. Defaults to the + * mutation's `state`. */ select?: (mutation: TMutation) => TResult } /** - * Collects the mutations in the cache that match `options.filters`, mapped with `options.select` - * (or to their state, by default). + * Collects the mutations in the cache that match `options.filters`, mapped with + * `options.select` (or to their state, by default). + * * @param mutationCache - The mutation cache to read. - * @param options - The `filters` to match and the `select` function to map each mutation with. + * @param options - The `filters` to match and the `select` function to map each + * mutation with. * @returns The selected value of every matching mutation. */ function getResult< @@ -136,77 +143,82 @@ function getResult< } /** - * `useMutationState` is a composable that gives you access to all mutations in the `MutationCache`. You can - * pass `filters` ({@link MutationFilters}) to narrow down your mutations, and `select` to transform the - * mutation state. - * - * `options` may be a plain object or a reactive getter (`() => ({ ... })`) — pass a getter if the filters - * themselves depend on other reactive state. - * @param options - The `filters` to narrow down matched mutations, and an optional `select` to transform the - * mutation state. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns A `ref` to an Array of whatever `select` returns for each matching mutation. + * `useMutationState` is a composable that gives you access to all mutations in + * the `MutationCache`. You can pass `filters` ({@link MutationFilters}) to + * narrow down your mutations, and `select` to transform the mutation state. + * + * `options` may be a plain object or a reactive getter (`() => ({ ... })`) — + * pass a getter if the filters themselves depend on other reactive state. + * * @example - * Get all variables of all running mutations: - * ```vue - * + * }) + * + * + * + * ``` * - * - * ``` * @example - * Get all data for specific mutations via the `mutationKey`: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Access the latest successful mutation data via the `mutationKey`. Each invocation of `mutate` adds a new - * entry to the mutation cache for `gcTime` milliseconds — with the `status: 'success'` filter below, check the - * last item that `useMutationState` returns to get the latest successful invocation: - * ```vue - * * - * const latestSavedPost = computed(() => savedPosts.value[savedPosts.value.length - 1]) - * + * + * ``` * - * - * ``` + * @param options - The `filters` to narrow down matched mutations, and an + * optional `select` to transform the mutation state. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns A `ref` to an Array of whatever `select` returns for each matching + * mutation. */ export function useMutationState< TResult = MutationState, diff --git a/packages/vue-query/src/usePrefetchInfiniteQuery.ts b/packages/vue-query/src/usePrefetchInfiniteQuery.ts index 4ac758f5fb3..5b4aacea96e 100644 --- a/packages/vue-query/src/usePrefetchInfiniteQuery.ts +++ b/packages/vue-query/src/usePrefetchInfiniteQuery.ts @@ -14,8 +14,8 @@ import type { QueryClient } from './queryClient' import type { MaybeRefDeep, MaybeRefOrGetter } from './types' /** - * The options accepted by `usePrefetchInfiniteQuery` — everything you can pass to `queryClient.infiniteQuery`, - * except that `queryFn` can't be `skipToken`. + * The options accepted by `usePrefetchInfiniteQuery` — everything you can pass + * to `queryClient.infiniteQuery`, except that `queryFn` can't be `skipToken`. */ export type UsePrefetchInfiniteQueryOptions< TQueryFnData, @@ -47,6 +47,7 @@ export type UsePrefetchInfiniteQueryOptions< /** * Checks whether an option was passed as a getter function. + * * @param value - The option value. * @returns `true` if `value` is a function. */ @@ -55,47 +56,57 @@ function isGetter(value: MaybeRefOrGetter): value is () => T { } /** - * `usePrefetchInfiniteQuery` does not return anything — it fires a prefetch as a reactive side effect, useful - * for kicking off a fetch ahead of the component that will actually render the data with `useInfiniteQuery`. - * You can pass everything to `usePrefetchInfiniteQuery` that you can pass to `queryClient.infiniteQuery`, - * though `queryKey`, `initialPageParam`, and `getNextPageParam` are always required, and `queryFn` is required - * unless a default query function has been defined. + * `usePrefetchInfiniteQuery` does not return anything — it fires a prefetch as + * a reactive side effect, useful for kicking off a fetch ahead of the component + * that will actually render the data with `useInfiniteQuery`. You can pass + * everything to `usePrefetchInfiniteQuery` that you can pass to + * `queryClient.infiniteQuery`, though `queryKey`, `initialPageParam`, and + * `getNextPageParam` are always required, and `queryFn` is required unless a + * default query function has been defined. * - * `getNextPageParam` receives both the last page of the infinite list of data and the full array of all pages, - * as well as pageParam information, and should return a single variable that will be passed to your query - * function as `context.pageParam`. Return `undefined` or `null` to indicate there is no next page available. + * `getNextPageParam` receives both the last page of the infinite list of data + * and the full array of all pages, as well as pageParam information, and should + * return a single variable that will be passed to your query function as + * `context.pageParam`. Return `undefined` or `null` to indicate there is no + * next page available. * - * The prefetch is skipped if the query already has any cached state — including a `pending`/`error` state left - * over from a previous attempt — so it won't refetch data that's already there or already in flight. It - * re-runs whenever a reactive dependency in `options` (built with `infiniteQueryOptions`, for example) changes. + * The prefetch is skipped if the query already has any cached state — including + * a `pending`/`error` state left over from a previous attempt — so it won't + * refetch data that's already there or already in flight. It re-runs whenever a + * reactive dependency in `options` (built with `infiniteQueryOptions`, for + * example) changes. + * + * Fire this during render, before a suspense boundary that wraps a component + * using `useInfiniteQuery`'s `suspense()` — see the + * {@link https://tanstack.com/query/latest/docs/framework/vue/guides/suspense | Suspense guide}. * - * Fire this during render, before a suspense boundary that wraps a component using `useInfiniteQuery`'s - * `suspense()` — see the {@link https://tanstack.com/query/latest/docs/framework/vue/guides/suspense | Suspense guide}. - * @param options - A `ref`, plain value, or reactive getter resolving to the - * {@link UsePrefetchInfiniteQueryOptions} to use — everything you can pass to `queryClient.infiniteQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. * @example - * ```vue - * + * // Fire the prefetch as soon as this component runs, before `Projects` mounts and calls `useInfiniteQuery`. + * usePrefetchInfiniteQuery(projectsOptions) + * * - * + * ``` + * + * @param options - A `ref`, plain value, or reactive getter resolving to the + * {@link UsePrefetchInfiniteQueryOptions} to use — everything you can pass to + * `queryClient.infiniteQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. */ export function usePrefetchInfiniteQuery< TQueryFnData = unknown, diff --git a/packages/vue-query/src/usePrefetchQuery.ts b/packages/vue-query/src/usePrefetchQuery.ts index e968d5af902..720219289b0 100644 --- a/packages/vue-query/src/usePrefetchQuery.ts +++ b/packages/vue-query/src/usePrefetchQuery.ts @@ -13,8 +13,8 @@ import type { QueryClient } from './queryClient' import type { MaybeRefDeep, MaybeRefOrGetter } from './types' /** - * The options accepted by `usePrefetchQuery` — everything you can pass to `queryClient.query`, except that - * `queryFn` can't be `skipToken`. + * The options accepted by `usePrefetchQuery` — everything you can pass to + * `queryClient.query`, except that `queryFn` can't be `skipToken`. */ export type UsePrefetchQueryOptions< TQueryFnData, @@ -48,6 +48,7 @@ export type UsePrefetchQueryOptions< /** * Checks whether an option was passed as a getter function. + * * @param value - The option value. * @returns `true` if `value` is a function. */ @@ -56,38 +57,46 @@ function isGetter(value: MaybeRefOrGetter): value is () => T { } /** - * `usePrefetchQuery` does not return anything — it fires a prefetch as a reactive side effect, useful for - * kicking off a fetch ahead of the component that will actually render the data with `useQuery`. You can pass - * everything to `usePrefetchQuery` that you can pass to `queryClient.query`, though `queryKey` is always - * required, and `queryFn` is required unless a default query function has been defined. + * `usePrefetchQuery` does not return anything — it fires a prefetch as a + * reactive side effect, useful for kicking off a fetch ahead of the component + * that will actually render the data with `useQuery`. You can pass everything + * to `usePrefetchQuery` that you can pass to `queryClient.query`, though + * `queryKey` is always required, and `queryFn` is required unless a default + * query function has been defined. + * + * The prefetch is skipped if the query already has any cached state — including + * a `pending`/`error` state left over from a previous attempt — so it won't + * refetch data that's already there or already in flight. It re-runs whenever a + * reactive dependency in `options` (built with `queryOptions`, for example) + * changes. * - * The prefetch is skipped if the query already has any cached state — including a `pending`/`error` state left - * over from a previous attempt — so it won't refetch data that's already there or already in flight. It - * re-runs whenever a reactive dependency in `options` (built with `queryOptions`, for example) changes. + * Fire this during render, before a suspense boundary that wraps a component + * using `useQuery`'s `suspense()` — see the + * {@link https://tanstack.com/query/latest/docs/framework/vue/guides/suspense | Suspense guide}. * - * Fire this during render, before a suspense boundary that wraps a component using `useQuery`'s `suspense()` - * — see the {@link https://tanstack.com/query/latest/docs/framework/vue/guides/suspense | Suspense guide}. - * @param options - A `ref`, plain value, or reactive getter resolving to the {@link UsePrefetchQueryOptions} to - * use — everything you can pass to `queryClient.query`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. * @example - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - A `ref`, plain value, or reactive getter resolving to the + * {@link UsePrefetchQueryOptions} to use — everything you can pass to + * `queryClient.query`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. */ export function usePrefetchQuery< TQueryFnData = unknown, diff --git a/packages/vue-query/src/useQueries.ts b/packages/vue-query/src/useQueries.ts index db7a000e9e8..9c8d0d24d5b 100644 --- a/packages/vue-query/src/useQueries.ts +++ b/packages/vue-query/src/useQueries.ts @@ -165,7 +165,8 @@ type GetUseQueryResult = QueryObserverResult /** - * UseQueriesOptions reducer recursively unwraps function arguments to infer/enforce type param + * UseQueriesOptions reducer recursively unwraps function arguments to + * infer/enforce type param */ export type UseQueriesOptions< T extends Array, @@ -206,9 +207,7 @@ export type UseQueriesOptions< : // Fallback Array -/** - * UseQueriesResults reducer recursively maps type param to results - */ +/** UseQueriesResults reducer recursively maps type param to results */ export type UseQueriesResults< T extends Array, TResults extends Array = [], @@ -232,124 +231,136 @@ type UseQueriesOptionsArg> = readonly [ ] /** - * The `useQueries` composable can be used to fetch a variable number of queries. + * The `useQueries` composable can be used to fetch a variable number of + * queries. * - * The `queries` option accepts an array of query option objects mostly identical to `useQuery`'s. It may be a - * plain array, a `ref`/reactive array (each entry tracked individually), or a getter function — pass a getter - * if the array itself (its length, or which queries are in it) depends on other reactive state. + * The `queries` option accepts an array of query option objects mostly + * identical to `useQuery`'s. It may be a plain array, a `ref`/reactive array + * (each entry tracked individually), or a getter function — pass a getter if + * the array itself (its length, or which queries are in it) depends on other + * reactive state. * - * Having the same query key more than once in the array of query objects may cause some data to be shared - * between queries. To avoid this, consider de-duplicating the queries and map the results back to the desired + * Having the same query key more than once in the array of query objects may + * cause some data to be shared between queries. To avoid this, consider + * de-duplicating the queries and map the results back to the desired * structure. * - * The `combine` option can be used to combine the results of the queries into a single value. The result will - * be structurally shared to be as referentially stable as possible. + * The `combine` option can be used to combine the results of the queries into a + * single value. The result will be structurally shared to be as referentially + * stable as possible. + * + * `placeholderData` is supported here too, but unlike `useQuery`, it doesn't + * receive information from previously rendered queries, because the number of + * queries can differ between renders. * - * `placeholderData` is supported here too, but unlike `useQuery`, it doesn't receive information from - * previously rendered queries, because the number of queries can differ between renders. - * @param options - The `queries` array to run, and the optional `combine` and `shallow` options. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns A `ref` to the combined result. Without `combine`, this is an array with all the query results, in - * the same order as the input. When `combine` is provided, this is the value returned by `combine` instead. * @example - * ```vue - * + * props.ids.map((id) => ({ + * queryKey: ['post', id], + * queryFn: () => fetchPost(id), + * staleTime: Infinity, + * })), + * }) + * * - * + * ``` + * * @example - * Combining results into a single value: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Typing `select` via {@link queryOptions}. Note that spreading a `queryOptions` result and overriding - * `select` inline still falls back to `unknown` — wrap the spread in `queryOptions` again so the override is - * resolved before it reaches `useQueries`: - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - The `queries` array to run, and the optional `combine` and + * `shallow` options. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns A `ref` to the combined result. Without `combine`, this is an array + * with all the query results, in the same order as the input. When `combine` + * is provided, this is the value returned by `combine` instead. */ export function useQueries< T extends Array, diff --git a/packages/vue-query/src/useQuery.ts b/packages/vue-query/src/useQuery.ts index 0e47e636804..14ba74f7ded 100644 --- a/packages/vue-query/src/useQuery.ts +++ b/packages/vue-query/src/useQuery.ts @@ -15,8 +15,9 @@ import type { } from './queryOptions' /** - * The result of `useQuery` when `initialData` is omitted or may be `undefined` — `data` may be `undefined` - * while the query is `pending`. See {@link UseBaseQueryReturnType}. + * The result of `useQuery` when `initialData` is omitted or may be `undefined` + * — `data` may be `undefined` while the query is `pending`. See + * {@link UseBaseQueryReturnType}. */ export type UseQueryReturnType = UseBaseQueryReturnType< TData, @@ -24,8 +25,8 @@ export type UseQueryReturnType = UseBaseQueryReturnType< > /** - * The result of `useQuery` when `initialData` is set — `data` is never `undefined` (unless a `select` changes - * `TData` to include `undefined`). + * The result of `useQuery` when `initialData` is set — `data` is never + * `undefined` (unless a `select` changes `TData` to include `undefined`). */ export type UseQueryDefinedReturnType = UseBaseQueryReturnType< TData, @@ -34,41 +35,46 @@ export type UseQueryDefinedReturnType = UseBaseQueryReturnType< > /** - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` or a reactive getter for the array itself, or `ref`s and - * reactive getters as individual entries. Other options are read once when passed as a plain value, and stay - * reactive when passed as a `ref` or a `computed`. - * @param options - The {@link DefinedInitialQueryOptions} to use — everything you can pass to `useQuery`, with - * `initialData` set. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The current query result, typed so that `data` is never `undefined` (unless a `select` changes - * `TData` to include `undefined`). `status` never resolves to `pending` in this overload's type, since - * `initialData` guarantees data upfront. + * This overload is selected when `initialData` is set, so the resulting `data` + * is never `undefined` (unless a `select` changes `TData` to include + * `undefined`). + * + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * or a reactive getter for the array itself, or `ref`s and reactive getters as + * individual entries. Other options are read once when passed as a plain value, + * and stay reactive when passed as a `ref` or a `computed`. + * * @example - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - The {@link DefinedInitialQueryOptions} to use — everything + * you can pass to `useQuery`, with `initialData` set. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The current query result, typed so that `data` is never `undefined` + * (unless a `select` changes `TData` to include `undefined`). `status` never + * resolves to `pending` in this overload's type, since `initialData` + * guarantees data upfront. */ export function useQuery< TQueryFnData = unknown, @@ -81,133 +87,142 @@ export function useQuery< ): UseQueryDefinedReturnType /** - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` or a reactive getter for the array itself, or `ref`s and - * reactive getters as individual entries. Other options are read once when passed as a plain value, and stay - * reactive when passed as a `ref` or a `computed`. - * @param options - The {@link UndefinedInitialQueryOptions} to use — everything you can pass to `useQuery`. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The current query result. `status` is `pending` if there is no cached data to display, `error` if - * the last fetch attempt failed, or `success` if the query has data to display. + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * or a reactive getter for the array itself, or `ref`s and reactive getters as + * individual entries. Other options are read once when passed as a plain value, + * and stay reactive when passed as a `ref` or a `computed`. + * * @example - * A query key built from a reactive `ref` — the query refetches whenever `postId` changes: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * `select` derives whatever `data` a component needs from the cached value, without changing what's - * actually stored in the cache — the cache still holds the full `Post[]`, but `data` here is a `number`: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * A dependent query, only enabled once `postId` is set — use `isLoading`, not `isPending`, so the - * loading state doesn't show while the query is disabled: - * ```vue - * + * }) + * * - * + * ``` + * * @example - * Seeding a detail query from an already-cached list, to skip the loading state. `initialDataUpdatedAt` carries - * over the list's own fetch time, so that if you set a `staleTime`, it's measured from when the list was - * fetched rather than from now: - * ```vue - * + * queryClient.getQueryState(['posts'])?.dataUpdatedAt, + * }) + * * - * + * ``` + * * @example - * Paginated data, keeping the previous page's data visible while the next page loads: - * ```vue - * + * }) + * * - * - * ``` + * ``` + * + * @param options - The {@link UndefinedInitialQueryOptions} to use — everything + * you can pass to `useQuery`. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The current query result. `status` is `pending` if there is no + * cached data to display, `error` if the last fetch attempt failed, or + * `success` if the query has data to display. */ export function useQuery< TQueryFnData = unknown, @@ -220,67 +235,75 @@ export function useQuery< ): UseQueryReturnType /** - * Fallback overload for options whose `initialData` presence isn't statically known — for example, a - * `ref`/reactive object built up conditionally, rather than a plain object literal. Prefer one of the other - * overloads when possible, since they infer whether `data` can be `undefined` from `initialData` directly. - * - * `enabled` tracks reactive dependencies automatically as a `ref`, a plain value, or a reactive getter - * (`() => ...`). `queryKey` reacts through a `ref` or a reactive getter for the array itself, or `ref`s and - * reactive getters as individual entries. - * - * When `options` itself is a reactive getter, the whole object is re-evaluated on every change to its - * dependencies, so any option inside it — not just `queryKey` and `enabled` — can change over time. - * @param options - A `ref`, plain value, or reactive getter resolving to the {@link UseQueryOptions} to use. - * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin` - * will be used. - * @returns The current query result, with `data` typed as possibly `undefined`. + * Fallback overload for options whose `initialData` presence isn't statically + * known — for example, a `ref`/reactive object built up conditionally, rather + * than a plain object literal. Prefer one of the other overloads when possible, + * since they infer whether `data` can be `undefined` from `initialData` + * directly. + * + * `enabled` tracks reactive dependencies automatically as a `ref`, a plain + * value, or a reactive getter (`() => ...`). `queryKey` reacts through a `ref` + * or a reactive getter for the array itself, or `ref`s and reactive getters as + * individual entries. + * + * When `options` itself is a reactive getter, the whole object is re-evaluated + * on every change to its dependencies, so any option inside it — not just + * `queryKey` and `enabled` — can change over time. + * * @example - * Passing a whole-options getter so `staleTime` reacts to a setting stored elsewhere, not just `queryKey`: - * ```vue - * + * })) + * * - * + * ``` + * * @example - * `skipToken` disables the query in a type-safe way, without a non-null assertion on `props.postId` — - * `queryFn` is only ever called when it's defined. The whole-options getter re-evaluates `queryFn` on every - * change to `props.postId`. `queryFn` can also be a `computed`, but never a bare getter, since a function - * there is the query function itself. `refetch` doesn't work while `queryFn` is `skipToken` — use - * `enabled: false` instead if you need to trigger the query manually: - * ```vue - * + * }) + * * - * + * ``` + * + * @param options - A `ref`, plain value, or reactive getter resolving to the + * {@link UseQueryOptions} to use. + * @param queryClient - Use this to use a custom `QueryClient`. Otherwise, the + * one provided by `VueQueryPlugin` will be used. + * @returns The current query result, with `data` typed as possibly `undefined`. */ export function useQuery< TQueryFnData = unknown, diff --git a/packages/vue-query/src/useQueryClient.ts b/packages/vue-query/src/useQueryClient.ts index 7c462669377..3be9b82900d 100644 --- a/packages/vue-query/src/useQueryClient.ts +++ b/packages/vue-query/src/useQueryClient.ts @@ -4,25 +4,28 @@ import { getClientKey } from './utils' import type { QueryClient } from './queryClient' /** - * Retrieves the `QueryClient` installed by `VueQueryPlugin`, via Vue's `inject`. Must be called inside - * `setup()` or another function that supports an injection context. - * @param id - The `queryClientKey` passed to `VueQueryPlugin` — only needed when multiple `QueryClient`s are - * installed in the same app. - * @returns The installed `QueryClient`. - * @throws {Error} If called outside an injection context, or if no `QueryClient` was installed via - * `VueQueryPlugin`. + * Retrieves the `QueryClient` installed by `VueQueryPlugin`, via Vue's + * `inject`. Must be called inside `setup()` or another function that supports + * an injection context. + * * @example - * ```vue - * - * ``` + * } + * + * ``` + * + * @param id - The `queryClientKey` passed to `VueQueryPlugin` — only needed + * when multiple `QueryClient`s are installed in the same app. + * @returns The installed `QueryClient`. + * @throws {Error} If called outside an injection context, or if no + * `QueryClient` was installed via `VueQueryPlugin`. */ export function useQueryClient(id = ''): QueryClient { // ensures that `inject()` can be used diff --git a/packages/vue-query/src/utils.ts b/packages/vue-query/src/utils.ts index 34bc29d4b0c..0e787cfe71b 100644 --- a/packages/vue-query/src/utils.ts +++ b/packages/vue-query/src/utils.ts @@ -3,15 +3,18 @@ import type { MaybeRefDeep } from './types' /** * Base Vue injection key `VueQueryPlugin` provides the `QueryClient` under. + * * @internal */ export const VUE_QUERY_CLIENT = 'VUE_QUERY_CLIENT' /** - * Builds the injection key `useQueryClient`/`VueQueryPlugin` use for a given `queryClientKey`. - * @internal + * Builds the injection key `useQueryClient`/`VueQueryPlugin` use for a given + * `queryClientKey`. + * * @param key - The `queryClientKey`. Without it, the base key is used. * @returns The injection key. + * @internal */ export function getClientKey(key?: string) { const suffix = key ? `:${key}` : '' @@ -19,10 +22,12 @@ export function getClientKey(key?: string) { } /** - * Copies each property from `update` onto `state`, in place, for every key already on `state`. - * @internal + * Copies each property from `update` onto `state`, in place, for every key + * already on `state`. + * * @param state - The object to update. * @param update - The object to copy the values from. + * @internal */ export function updateState( state: Record, @@ -34,11 +39,13 @@ export function updateState( } /** - * Recursive implementation of {@link cloneDeep}, which also tracks the key and nesting level of - * the current node for `customize`. + * Recursive implementation of {@link cloneDeep}, which also tracks the key and + * nesting level of the current node for `customize`. + * * @param value - The value to clone. - * @param customize - Called for every node with its key and nesting level. If it returns a value - * other than `undefined`, that value is used instead of recursing. + * @param customize - Called for every node with its key and nesting level. If + * it returns a value other than `undefined`, that value is used instead of + * recursing. * @param currentKey - The key of the current node. * @param currentLevel - The nesting level of the current node. * @returns The cloned value. @@ -81,14 +88,16 @@ function _cloneDeep( } /** - * Deep-clones `value`, recursing into arrays and plain objects. `customize`, if provided, can - * intercept any node (by key and nesting level) and substitute its own return value instead of recursing - * further. - * @internal + * Deep-clones `value`, recursing into arrays and plain objects. `customize`, if + * provided, can intercept any node (by key and nesting level) and substitute + * its own return value instead of recursing further. + * * @param value - The value to clone. - * @param customize - Called for every node with its key and nesting level. If it returns a value - * other than `undefined`, that value is used instead of recursing. + * @param customize - Called for every node with its key and nesting level. If + * it returns a value other than `undefined`, that value is used instead of + * recursing. * @returns The cloned value. + * @internal */ export function cloneDeep( value: MaybeRefDeep, @@ -102,14 +111,16 @@ export function cloneDeep( } /** - * Deep-clones `value` like {@link cloneDeep}, additionally unwrapping any `ref`s it encounters (and, - * if `unrefGetters` is `true`, calling any functions it encounters and unwrapping their result too). Always - * resolves `queryKey` this way, regardless of `unrefGetters` — this is what lets a `queryKey` containing `ref`s - * be passed straight through to `@tanstack/query-core`. - * @internal + * Deep-clones `value` like {@link cloneDeep}, additionally unwrapping any `ref`s + * it encounters (and, if `unrefGetters` is `true`, calling any functions it + * encounters and unwrapping their result too). Always resolves `queryKey` this + * way, regardless of `unrefGetters` — this is what lets a `queryKey` containing + * `ref`s be passed straight through to `@tanstack/query-core`. + * * @param obj - The value to clone. * @param unrefGetters - Whether to also call functions and unwrap their result. * @returns The cloned value, with `ref`s unwrapped. + * @internal */ export function cloneDeepUnref( obj: MaybeRefDeep, @@ -143,6 +154,7 @@ export function cloneDeepUnref( /** * Checks whether a value is a plain object, created with an object literal or * `Object.create(null)`. + * * @param value - The value to check. * @returns `true` if `value` is a plain object. */ @@ -158,6 +170,7 @@ function isPlainObject(value: unknown): value is Object { /** * Checks whether a value is a function. + * * @param value - The value to check. * @returns `true` if `value` is a function. */ @@ -166,10 +179,12 @@ function isFunction(value: unknown): value is Function { } /** - * Resolves `source` to a plain value — calls it if it's a function, otherwise deep-unwraps it. - * @internal + * Resolves `source` to a plain value — calls it if it's a function, otherwise + * deep-unwraps it. + * * @param source - A getter, or a value that may contain `ref`s. * @returns The resolved plain value. + * @internal */ export function toValueDeep(source: (() => T) | MaybeRefDeep): T { return isFunction(source) ? source() : cloneDeepUnref(source) diff --git a/packages/vue-query/src/vueQueryPlugin.ts b/packages/vue-query/src/vueQueryPlugin.ts index d74b2b172fa..5097d1e18d2 100644 --- a/packages/vue-query/src/vueQueryPlugin.ts +++ b/packages/vue-query/src/vueQueryPlugin.ts @@ -9,68 +9,88 @@ import type { QueryClientConfig } from './types' type ClientPersister = (client: QueryClient) => [() => void, Promise] interface CommonOptions { - /** Enables the legacy Vue Devtools v6 plugin panel. Prefer `@tanstack/vue-query-devtools` for Vue 3 apps. */ + /** + * Enables the legacy Vue Devtools v6 plugin panel. Prefer + * `@tanstack/vue-query-devtools` for Vue 3 apps. + */ enableDevtoolsV6Plugin?: boolean /** - * Distinguishes multiple `QueryClient`s provided in the same app — pass the same key to `useQueryClient` to - * pick this one. Only needed when installing more than one client. + * Distinguishes multiple `QueryClient`s provided in the same app — pass the + * same key to `useQueryClient` to pick this one. Only needed when installing + * more than one client. */ queryClientKey?: string /** - * Restores a persisted cache before the app mounts. While it runs, `queryClient.isRestoring` is `true`, which - * suppresses fetches — see `usePersistQueryClient` in `@tanstack/query-persist-client-core` for building one. + * Restores a persisted cache before the app mounts. While it runs, + * `queryClient.isRestoring` is `true`, which suppresses fetches — see + * `usePersistQueryClient` in `@tanstack/query-persist-client-core` for + * building one. */ clientPersister?: ClientPersister - /** Called once `clientPersister`'s returned promise resolves and the cache has finished restoring. */ + /** + * Called once `clientPersister`'s returned promise resolves and the cache has + * finished restoring. + */ clientPersisterOnSuccess?: (client: QueryClient) => void } interface ConfigOptions extends CommonOptions { - /** Options for the `QueryClient` the plugin constructs. Ignored if `queryClient` is also set. */ + /** + * Options for the `QueryClient` the plugin constructs. Ignored if + * `queryClient` is also set. + */ queryClientConfig?: QueryClientConfig } interface ClientOptions extends CommonOptions { - /** Use your own `QueryClient` instance instead of having the plugin construct one from `queryClientConfig`. */ + /** + * Use your own `QueryClient` instance instead of having the plugin construct + * one from `queryClientConfig`. + */ queryClient?: QueryClient } /** - * The options accepted by `VueQueryPlugin`: either a `queryClient` to install, or a `queryClientConfig` for the - * client the plugin creates, plus the shared options. + * The options accepted by `VueQueryPlugin`: either a `queryClient` to install, + * or a `queryClientConfig` for the client the plugin creates, plus the shared + * options. */ export type VueQueryPluginOptions = ConfigOptions | ClientOptions /** - * Installs a `QueryClient` on the Vue app, making it available to every descendant component through - * `useQueryClient` — the Vue equivalent of React's `QueryClientProvider`, but wired up as an app-level plugin - * instead of a wrapping component. + * Installs a `QueryClient` on the Vue app, making it available to every + * descendant component through `useQueryClient` — the Vue equivalent of React's + * `QueryClientProvider`, but wired up as an app-level plugin instead of a + * wrapping component. + * * @example - * ```ts - * import { createApp } from 'vue' - * import { VueQueryPlugin } from '@tanstack/vue-query' + * ```ts + * import { createApp } from 'vue' + * import { VueQueryPlugin } from '@tanstack/vue-query' + * + * const app = createApp(App) + * app.use(VueQueryPlugin) + * ``` * - * const app = createApp(App) - * app.use(VueQueryPlugin) - * ``` * @example - * Pass a `queryClient` you constructed yourself — useful for SSR, where you need a fresh `QueryClient` per - * request, or when the same instance also needs to be used outside of Vue components: - * ```ts - * import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' + * Pass a `queryClient` you constructed yourself — useful for SSR, where you need a fresh `QueryClient` per + * request, or when the same instance also needs to be used outside of Vue components: + * ```ts + * import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' + * + * const queryClient = new QueryClient() + * app.use(VueQueryPlugin, { queryClient }) + * ``` * - * const queryClient = new QueryClient() - * app.use(VueQueryPlugin, { queryClient }) - * ``` * @example - * Or pass `queryClientConfig` to let the plugin construct the `QueryClient` for you, with your own defaults: - * ```ts - * app.use(VueQueryPlugin, { + * Or pass `queryClientConfig` to let the plugin construct the `QueryClient` for you, with your own defaults: + * ```ts + * app.use(VueQueryPlugin, { * queryClientConfig: { - * defaultOptions: { queries: { staleTime: 5 * 1000 } }, + * defaultOptions: { queries: { staleTime: 5 * 1000 } }, * }, - * }) - * ``` + * }) + * ``` */ export const VueQueryPlugin = { install: (app: any, options: VueQueryPluginOptions = {}) => { From b3908bd6de685996ac708b123484212de2000527 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2026 15:42:43 +0000 Subject: [PATCH 2/4] ci: apply automated fixes --- .../src/providers.ts | 2 +- .../angular-query-experimental/src/types.ts | 4 +- packages/lit-query/src/QueryClientProvider.ts | 22 ++++----- packages/lit-query/src/accessor.ts | 4 +- .../src/createInfiniteQueryController.ts | 34 ++++++------- .../lit-query/src/createMutationController.ts | 36 +++++++------- .../lit-query/src/createQueriesController.ts | 30 ++++++------ .../lit-query/src/createQueryController.ts | 24 +++++----- .../lit-query/src/infiniteQueryOptions.ts | 2 +- packages/lit-query/src/mutationOptions.ts | 2 +- packages/lit-query/src/queryOptions.ts | 2 +- packages/lit-query/src/useIsFetching.ts | 12 ++--- packages/lit-query/src/useIsMutating.ts | 12 ++--- packages/lit-query/src/useMutationState.ts | 14 +++--- .../preact-query/src/HydrationBoundary.tsx | 2 +- .../preact-query/src/QueryClientProvider.tsx | 2 +- .../src/QueryErrorResetBoundary.tsx | 4 +- .../preact-query/src/infiniteQueryOptions.ts | 40 ++++++++-------- packages/preact-query/src/mutationOptions.ts | 2 +- packages/preact-query/src/queryOptions.ts | 32 ++++++------- packages/preact-query/src/useInfiniteQuery.ts | 40 ++++++++-------- packages/preact-query/src/useIsFetching.ts | 2 +- packages/preact-query/src/useMutation.ts | 2 +- packages/preact-query/src/useMutationState.ts | 2 +- .../src/usePrefetchInfiniteQuery.tsx | 2 +- .../preact-query/src/usePrefetchQuery.tsx | 2 +- packages/preact-query/src/useQueries.ts | 2 +- packages/preact-query/src/useQuery.ts | 38 +++++++-------- packages/query-core/src/environmentManager.ts | 2 +- packages/query-core/src/focusManager.ts | 4 +- packages/query-core/src/hydration.ts | 2 +- .../query-core/src/infiniteQueryObserver.ts | 6 +-- packages/query-core/src/mutation.ts | 4 +- packages/query-core/src/mutationCache.ts | 12 ++--- packages/query-core/src/mutationObserver.ts | 10 ++-- packages/query-core/src/notifyManager.ts | 4 +- packages/query-core/src/onlineManager.ts | 4 +- packages/query-core/src/queriesObserver.ts | 6 +-- packages/query-core/src/query.ts | 12 ++--- packages/query-core/src/queryCache.ts | 16 +++---- packages/query-core/src/queryClient.ts | 48 +++++++++---------- packages/query-core/src/queryObserver.ts | 12 ++--- packages/query-core/src/retryer.ts | 8 ++-- packages/query-core/src/streamedQuery.ts | 2 +- packages/query-core/src/subscribable.ts | 2 +- packages/query-core/src/timeoutManager.ts | 10 ++-- packages/query-core/src/types.ts | 2 +- packages/query-core/src/utils.ts | 18 +++---- .../react-query/src/HydrationBoundary.tsx | 2 +- .../react-query/src/QueryClientProvider.tsx | 2 +- .../src/QueryErrorResetBoundary.tsx | 4 +- .../react-query/src/infiniteQueryOptions.ts | 40 ++++++++-------- packages/react-query/src/mutationOptions.ts | 2 +- packages/react-query/src/queryOptions.ts | 32 ++++++------- packages/react-query/src/useInfiniteQuery.ts | 40 ++++++++-------- packages/react-query/src/useIsFetching.ts | 2 +- packages/react-query/src/useMutation.ts | 2 +- packages/react-query/src/useMutationState.ts | 2 +- .../src/usePrefetchInfiniteQuery.tsx | 2 +- packages/react-query/src/usePrefetchQuery.tsx | 2 +- packages/react-query/src/useQueries.ts | 2 +- packages/react-query/src/useQuery.ts | 38 +++++++-------- .../solid-query/src/QueryClientProvider.tsx | 2 +- .../solid-query/src/infiniteQueryOptions.ts | 48 +++++++++---------- packages/solid-query/src/mutationOptions.ts | 2 +- packages/solid-query/src/queryOptions.ts | 32 ++++++------- packages/solid-query/src/useInfiniteQuery.ts | 48 +++++++++---------- packages/solid-query/src/useIsFetching.ts | 2 +- packages/solid-query/src/useIsMutating.ts | 2 +- packages/solid-query/src/useMutation.ts | 2 +- packages/solid-query/src/useQueries.ts | 2 +- packages/solid-query/src/useQuery.ts | 36 +++++++------- packages/svelte-query/src/context.ts | 2 +- .../svelte-query/src/createMutation.svelte.ts | 2 +- .../svelte-query/src/createQueries.svelte.ts | 2 +- packages/svelte-query/src/createQuery.ts | 2 +- packages/svelte-query/src/mutationOptions.ts | 2 +- .../svelte-query/src/useIsFetching.svelte.ts | 2 +- .../svelte-query/src/useIsMutating.svelte.ts | 2 +- packages/svelte-query/src/useIsRestoring.ts | 2 +- packages/svelte-query/src/useQueryClient.ts | 2 +- .../vue-query/src/infiniteQueryOptions.ts | 2 +- packages/vue-query/src/mutationOptions.ts | 47 +++++++++--------- packages/vue-query/src/useIsFetching.ts | 2 +- packages/vue-query/src/useMutation.ts | 2 +- packages/vue-query/src/useMutationState.ts | 2 +- packages/vue-query/src/useQueries.ts | 2 +- packages/vue-query/src/useQueryClient.ts | 2 +- packages/vue-query/src/vueQueryPlugin.ts | 2 +- 89 files changed, 492 insertions(+), 491 deletions(-) diff --git a/packages/angular-query-experimental/src/providers.ts b/packages/angular-query-experimental/src/providers.ts index f75ce23e52b..32e4192ac5d 100644 --- a/packages/angular-query-experimental/src/providers.ts +++ b/packages/angular-query-experimental/src/providers.ts @@ -48,7 +48,7 @@ export function provideQueryClient( * features such as developer tools. * * @example - * ```ts + * ;```ts * import { * provideTanStackQuery, * QueryClient, diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index 12f5016cd32..ee33b80feb0 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -81,8 +81,8 @@ type CreateStatusBasedQueryResult< * the branch, the same way `status` narrowing works on the plain object * `react-query` returns. * - * @template TData - The type `data` ends up as after `select` runs. - * @template TError - The type of errors your `queryFn` may throw. + * @template TData - The type `data` ends up as after `select` runs. @template + * TError - The type of errors your `queryFn` may throw. */ export interface BaseQueryNarrowing { /** diff --git a/packages/lit-query/src/QueryClientProvider.ts b/packages/lit-query/src/QueryClientProvider.ts index a13a41b217d..ade324225ba 100644 --- a/packages/lit-query/src/QueryClientProvider.ts +++ b/packages/lit-query/src/QueryClientProvider.ts @@ -30,20 +30,20 @@ import type { TemplateResult } from 'lit' * const queryClient = new QueryClient() * * class AppQueryProvider extends QueryClientProvider { - * constructor() { - * super() - * this.client = queryClient - * } + * constructor() { + * super() + * this.client = queryClient + * } * } * * customElements.define('app-query-provider', AppQueryProvider) * * class AppRoot extends LitElement { - * render() { - * return html`` - * } + * render() { + * return html`` + * } * } * ``` * @@ -58,9 +58,9 @@ import type { TemplateResult } from 'lit' * * const view = html` * - * + * * - * ` + * ` * ``` */ export class QueryClientProvider extends LitElement { diff --git a/packages/lit-query/src/accessor.ts b/packages/lit-query/src/accessor.ts index fbb4d1bb200..cf5e8d2924a 100644 --- a/packages/lit-query/src/accessor.ts +++ b/packages/lit-query/src/accessor.ts @@ -5,7 +5,7 @@ * depend on reactive host state. * * @example - * ```ts + * ;```ts * const staticKey: Accessor = ['todos'] * const reactiveKey: Accessor = () => [ * 'todos', @@ -34,7 +34,7 @@ export function readAccessor(value: Accessor): T { * can use either `result()` or `result.current`. * * @example - * ```ts + * ;```ts * const query = this.todos() * const sameQuery = this.todos.current * ``` diff --git a/packages/lit-query/src/createInfiniteQueryController.ts b/packages/lit-query/src/createInfiniteQueryController.ts index 28f994b33b2..7dc8f4774c1 100644 --- a/packages/lit-query/src/createInfiniteQueryController.ts +++ b/packages/lit-query/src/createInfiniteQueryController.ts @@ -373,25 +373,25 @@ class InfiniteQueryController< * import { createInfiniteQueryController } from '@tanstack/lit-query' * * class ProjectsView extends LitElement { - * private readonly projects = createInfiniteQueryController(this, { - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextCursor, - * }) + * private readonly projects = createInfiniteQueryController(this, { + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextCursor, + * }) * - * render() { - * const query = this.projects() + * render() { + * const query = this.projects() * - * return html` - * - * ` - * } + * return html` + * + * ` + * } * } * ``` * diff --git a/packages/lit-query/src/createMutationController.ts b/packages/lit-query/src/createMutationController.ts index 88162dd4aaa..bd47dec2cf4 100644 --- a/packages/lit-query/src/createMutationController.ts +++ b/packages/lit-query/src/createMutationController.ts @@ -301,26 +301,26 @@ class MutationController< * import { createMutationController } from '@tanstack/lit-query' * * class AddTodoForm extends LitElement { - * private readonly addTodo = createMutationController(this, { - * mutationFn: (title: string) => - * fetch('/api/todos', { - * method: 'POST', - * body: JSON.stringify({ title }), - * }), - * }) + * private readonly addTodo = createMutationController(this, { + * mutationFn: (title: string) => + * fetch('/api/todos', { + * method: 'POST', + * body: JSON.stringify({ title }), + * }), + * }) * - * render() { - * const mutation = this.addTodo() + * render() { + * const mutation = this.addTodo() * - * return html` - * - * ` - * } + * return html` + * + * ` + * } * } * ``` * diff --git a/packages/lit-query/src/createQueriesController.ts b/packages/lit-query/src/createQueriesController.ts index 4ce71e330cd..f95748c7949 100644 --- a/packages/lit-query/src/createQueriesController.ts +++ b/packages/lit-query/src/createQueriesController.ts @@ -687,22 +687,22 @@ class QueriesController< * import { createQueriesController } from '@tanstack/lit-query' * * class DashboardView extends LitElement { - * private readonly dashboard = createQueriesController(this, { - * queries: [ - * { queryKey: ['stats'], queryFn: fetchStats }, - * { queryKey: ['projects'], queryFn: fetchProjects }, - * ], - * combine: ([stats, projects]) => ({ - * stats: stats.data, - * projects: projects.data ?? [], - * isPending: stats.isPending || projects.isPending, - * }), - * }) + * private readonly dashboard = createQueriesController(this, { + * queries: [ + * { queryKey: ['stats'], queryFn: fetchStats }, + * { queryKey: ['projects'], queryFn: fetchProjects }, + * ], + * combine: ([stats, projects]) => ({ + * stats: stats.data, + * projects: projects.data ?? [], + * isPending: stats.isPending || projects.isPending, + * }), + * }) * - * render() { - * const dashboard = this.dashboard() - * return html`

Projects: ${dashboard.projects.length}

` - * } + * render() { + * const dashboard = this.dashboard() + * return html`

Projects: ${dashboard.projects.length}

` + * } * } * ``` * diff --git a/packages/lit-query/src/createQueryController.ts b/packages/lit-query/src/createQueryController.ts index eefd6a6fe04..151142fa018 100644 --- a/packages/lit-query/src/createQueryController.ts +++ b/packages/lit-query/src/createQueryController.ts @@ -325,21 +325,21 @@ class QueryController< * import { createQueryController } from '@tanstack/lit-query' * * class TodosView extends LitElement { - * private readonly todos = createQueryController(this, { - * queryKey: ['todos'], - * queryFn: async () => fetch('/api/todos').then((r) => r.json()), - * }) + * private readonly todos = createQueryController(this, { + * queryKey: ['todos'], + * queryFn: async () => fetch('/api/todos').then((r) => r.json()), + * }) * - * render() { - * const query = this.todos() + * render() { + * const query = this.todos() * - * if (query.isPending) return html`Loading...` - * if (query.isError) return html`Error` + * if (query.isPending) return html`Loading...` + * if (query.isError) return html`Error` * - * return html`
    - * ${query.data.map((todo) => html`
  • ${todo.title}
  • `)} - *
` - * } + * return html`
    + * ${query.data.map((todo) => html`
  • ${todo.title}
  • `)} + *
` + * } * } * ``` * diff --git a/packages/lit-query/src/infiniteQueryOptions.ts b/packages/lit-query/src/infiniteQueryOptions.ts index 7031ae8ca65..c5c5c29ae1c 100644 --- a/packages/lit-query/src/infiniteQueryOptions.ts +++ b/packages/lit-query/src/infiniteQueryOptions.ts @@ -11,7 +11,7 @@ import type { * data and error types across TanStack Query APIs. * * @example - * ```ts + * ;```ts * import { infiniteQueryOptions } from '@tanstack/lit-query' * * const projectsOptions = infiniteQueryOptions({ diff --git a/packages/lit-query/src/mutationOptions.ts b/packages/lit-query/src/mutationOptions.ts index 0e0329f76a2..c092a6d9a5b 100644 --- a/packages/lit-query/src/mutationOptions.ts +++ b/packages/lit-query/src/mutationOptions.ts @@ -7,7 +7,7 @@ import type { * Preserves and types mutation options for reuse across Lit Query APIs. * * @example - * ```ts + * ;```ts * import { mutationOptions } from '@tanstack/lit-query' * * const addTodoOptions = mutationOptions({ diff --git a/packages/lit-query/src/queryOptions.ts b/packages/lit-query/src/queryOptions.ts index 80daa6e62ad..e90b8f1f31c 100644 --- a/packages/lit-query/src/queryOptions.ts +++ b/packages/lit-query/src/queryOptions.ts @@ -72,7 +72,7 @@ export type UndefinedInitialDataOptions< * error types across TanStack Query APIs. * * @example - * ```ts + * ;```ts * import { queryOptions } from '@tanstack/lit-query' * * const todosOptions = queryOptions({ diff --git a/packages/lit-query/src/useIsFetching.ts b/packages/lit-query/src/useIsFetching.ts index 289fd0ad080..dc1d6ead293 100644 --- a/packages/lit-query/src/useIsFetching.ts +++ b/packages/lit-query/src/useIsFetching.ts @@ -123,13 +123,13 @@ class IsFetchingController extends BaseController { * import { useIsFetching } from '@tanstack/lit-query' * * class TodosStatus extends LitElement { - * private readonly todosFetching = useIsFetching(this, { - * queryKey: ['todos'], - * }) + * private readonly todosFetching = useIsFetching(this, { + * queryKey: ['todos'], + * }) * - * render() { - * return html`${this.todosFetching()} active todo fetches` - * } + * render() { + * return html`${this.todosFetching()} active todo fetches` + * } * } * ``` * diff --git a/packages/lit-query/src/useIsMutating.ts b/packages/lit-query/src/useIsMutating.ts index 9665043c1f6..1d82a4abb6c 100644 --- a/packages/lit-query/src/useIsMutating.ts +++ b/packages/lit-query/src/useIsMutating.ts @@ -123,13 +123,13 @@ class IsMutatingController extends BaseController { * import { useIsMutating } from '@tanstack/lit-query' * * class MutationStatus extends LitElement { - * private readonly savesPending = useIsMutating(this, { - * mutationKey: ['save-project'], - * }) + * private readonly savesPending = useIsMutating(this, { + * mutationKey: ['save-project'], + * }) * - * render() { - * return html`${this.savesPending()} saves pending` - * } + * render() { + * return html`${this.savesPending()} saves pending` + * } * } * ``` * diff --git a/packages/lit-query/src/useMutationState.ts b/packages/lit-query/src/useMutationState.ts index 315f4d6ecf4..e781b4c6d72 100644 --- a/packages/lit-query/src/useMutationState.ts +++ b/packages/lit-query/src/useMutationState.ts @@ -165,14 +165,14 @@ class MutationStateController extends BaseController> { * import { useMutationState } from '@tanstack/lit-query' * * class PendingUploads extends LitElement { - * private readonly uploads = useMutationState(this, { - * filters: { mutationKey: ['upload'], status: 'pending' }, - * select: (mutation) => mutation.state.variables as File, - * }) + * private readonly uploads = useMutationState(this, { + * filters: { mutationKey: ['upload'], status: 'pending' }, + * select: (mutation) => mutation.state.variables as File, + * }) * - * render() { - * return html`${this.uploads().length} uploads pending` - * } + * render() { + * return html`${this.uploads().length} uploads pending` + * } * } * ``` * diff --git a/packages/preact-query/src/HydrationBoundary.tsx b/packages/preact-query/src/HydrationBoundary.tsx index 659c0b5fc22..4544e23a4df 100644 --- a/packages/preact-query/src/HydrationBoundary.tsx +++ b/packages/preact-query/src/HydrationBoundary.tsx @@ -46,7 +46,7 @@ export interface HydrationBoundaryProps { * Note: Only `queries` can be dehydrated with an `HydrationBoundary`. * * @example - * ```tsx + * ;```tsx * import { HydrationBoundary } from '@tanstack/preact-query' * * function App() { diff --git a/packages/preact-query/src/QueryClientProvider.tsx b/packages/preact-query/src/QueryClientProvider.tsx index 87880faa4bd..b3c86c369f2 100644 --- a/packages/preact-query/src/QueryClientProvider.tsx +++ b/packages/preact-query/src/QueryClientProvider.tsx @@ -54,7 +54,7 @@ export type QueryClientProviderProps = { * and refetching as needed when the app regains focus or comes back online). * * @example - * ```tsx + * ;```tsx * import { QueryClient, QueryClientProvider } from '@tanstack/preact-query' * * const queryClient = new QueryClient() diff --git a/packages/preact-query/src/QueryErrorResetBoundary.tsx b/packages/preact-query/src/QueryErrorResetBoundary.tsx index 7c9d00ceafd..e5a44050a62 100644 --- a/packages/preact-query/src/QueryErrorResetBoundary.tsx +++ b/packages/preact-query/src/QueryErrorResetBoundary.tsx @@ -69,7 +69,7 @@ const QueryErrorResetBoundaryContext = createContext(createValue()) * globally. * * @example - * ```tsx + * ;```tsx * import { useErrorBoundary } from 'preact/hooks' * import type { ComponentChildren } from 'preact' * import { useQueryErrorResetBoundary } from '@tanstack/preact-query' @@ -124,7 +124,7 @@ export interface QueryErrorResetBoundaryProps { * any query errors within the boundaries of the component. * * @example - * ```tsx + * ;```tsx * import { useErrorBoundary } from 'preact/hooks' * import type { ComponentChildren } from 'preact' * import { QueryErrorResetBoundary } from '@tanstack/preact-query' diff --git a/packages/preact-query/src/infiniteQueryOptions.ts b/packages/preact-query/src/infiniteQueryOptions.ts index 20add019767..0817f75abf8 100644 --- a/packages/preact-query/src/infiniteQueryOptions.ts +++ b/packages/preact-query/src/infiniteQueryOptions.ts @@ -157,33 +157,33 @@ export type DefinedInitialDataInfiniteOptions< * @example * ```tsx * import { - * infiniteQueryOptions, - * useInfiniteQuery, + * infiniteQueryOptions, + * useInfiniteQuery, * } from '@tanstack/preact-query' * * export const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, * }) * * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery(projectsOptions) + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery(projectsOptions) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => - * page.projects.map((p) =>
  • {p.name}
  • ), - * )} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) * } * ``` * diff --git a/packages/preact-query/src/mutationOptions.ts b/packages/preact-query/src/mutationOptions.ts index 68c3245b8ba..d135309f69a 100644 --- a/packages/preact-query/src/mutationOptions.ts +++ b/packages/preact-query/src/mutationOptions.ts @@ -56,7 +56,7 @@ export function mutationOptions< * See the other overload's example for looking a mutation up via * `useMutationState`. * @example - * ```tsx + * ;```tsx * import { mutationOptions, useMutation } from '@tanstack/preact-query' * * export const createPostOptions = mutationOptions({ diff --git a/packages/preact-query/src/queryOptions.ts b/packages/preact-query/src/queryOptions.ts index be75d5f9585..9820901507c 100644 --- a/packages/preact-query/src/queryOptions.ts +++ b/packages/preact-query/src/queryOptions.ts @@ -126,26 +126,26 @@ export type DefinedInitialDataOptions< * import { queryOptions, useQuery } from '@tanstack/preact-query' * * export const postsOptions = queryOptions({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], * }) * * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery(postsOptions) + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery(postsOptions) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) * } * ``` * diff --git a/packages/preact-query/src/useInfiniteQuery.ts b/packages/preact-query/src/useInfiniteQuery.ts index 32d8159b25b..0c1adf53103 100644 --- a/packages/preact-query/src/useInfiniteQuery.ts +++ b/packages/preact-query/src/useInfiniteQuery.ts @@ -35,26 +35,26 @@ import type { * import { useInfiniteQuery } from '@tanstack/preact-query' * * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * }) - * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => - * page.projects.map((p) =>
  • {p.name}
  • ), - * )} - *
- *
- * ) + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, + * }) + * + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) * } * ``` * diff --git a/packages/preact-query/src/useIsFetching.ts b/packages/preact-query/src/useIsFetching.ts index ff337c9169f..db1ffb46226 100644 --- a/packages/preact-query/src/useIsFetching.ts +++ b/packages/preact-query/src/useIsFetching.ts @@ -11,7 +11,7 @@ import type { QueryClient, QueryFilters } from '@tanstack/query-core' * loading indicators). * * @example - * ```tsx + * ;```tsx * import { useIsFetching } from '@tanstack/preact-query' * * function PostsFetchingIndicator() { diff --git a/packages/preact-query/src/useMutation.ts b/packages/preact-query/src/useMutation.ts index 2c9b873637f..a359336b1a4 100644 --- a/packages/preact-query/src/useMutation.ts +++ b/packages/preact-query/src/useMutation.ts @@ -22,7 +22,7 @@ import type { DefaultError, QueryClient } from '@tanstack/query-core' * perform server side-effects. `useMutation` is the hook for that. * * @example - * ```tsx + * ;```tsx * import { useMutation, useQueryClient } from '@tanstack/preact-query' * * function AddTodo() { diff --git a/packages/preact-query/src/useMutationState.ts b/packages/preact-query/src/useMutationState.ts index 314103ab270..707f2c9eba8 100644 --- a/packages/preact-query/src/useMutationState.ts +++ b/packages/preact-query/src/useMutationState.ts @@ -17,7 +17,7 @@ import type { * indicators). * * @example - * ```tsx + * ;```tsx * import { useIsMutating } from '@tanstack/preact-query' * * function PostsMutatingIndicator() { diff --git a/packages/preact-query/src/usePrefetchInfiniteQuery.tsx b/packages/preact-query/src/usePrefetchInfiniteQuery.tsx index 5b32a859244..40a811d234b 100644 --- a/packages/preact-query/src/usePrefetchInfiniteQuery.tsx +++ b/packages/preact-query/src/usePrefetchInfiniteQuery.tsx @@ -25,7 +25,7 @@ import type { UsePrefetchInfiniteQueryOptions } from './types' * already in flight. * * @example - * ```tsx + * ;```tsx * import { Suspense } from 'preact/compat' * import { * infiniteQueryOptions, diff --git a/packages/preact-query/src/usePrefetchQuery.tsx b/packages/preact-query/src/usePrefetchQuery.tsx index ae2910d7a5a..ccdd795e694 100644 --- a/packages/preact-query/src/usePrefetchQuery.tsx +++ b/packages/preact-query/src/usePrefetchQuery.tsx @@ -18,7 +18,7 @@ import type { UsePrefetchQueryOptions } from './types' * already in flight. * * @example - * ```tsx + * ;```tsx * import { Suspense } from 'preact/compat' * import { usePrefetchQuery } from '@tanstack/preact-query' * diff --git a/packages/preact-query/src/useQueries.ts b/packages/preact-query/src/useQueries.ts index cbf6b5e3a20..4c4e156bf64 100644 --- a/packages/preact-query/src/useQueries.ts +++ b/packages/preact-query/src/useQueries.ts @@ -248,7 +248,7 @@ export type QueriesResults< * stable as possible. * * @example - * ```tsx + * ;```tsx * import { useQueries } from '@tanstack/preact-query' * * function Posts({ ids }: { ids: Array }) { diff --git a/packages/preact-query/src/useQuery.ts b/packages/preact-query/src/useQuery.ts index 8b3ffcd3b5b..edbc4e30c58 100644 --- a/packages/preact-query/src/useQuery.ts +++ b/packages/preact-query/src/useQuery.ts @@ -22,24 +22,24 @@ import type { * import { useQuery } from '@tanstack/preact-query' * * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * }) + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * }) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) * } * ``` * @@ -69,7 +69,7 @@ export function useQuery< * `undefined`, so the resulting `data` can be `undefined`. * * @example - * ```tsx + * ;```tsx * import { useQuery } from '@tanstack/preact-query' * * function Posts() { @@ -143,7 +143,7 @@ export function useQuery< * infer whether `data` can be `undefined` from `initialData` directly. * * @example - * ```tsx + * ;```tsx * import { useQuery } from '@tanstack/preact-query' * * function Posts() { diff --git a/packages/query-core/src/environmentManager.ts b/packages/query-core/src/environmentManager.ts index 425ff6ab772..01b64c6f70e 100644 --- a/packages/query-core/src/environmentManager.ts +++ b/packages/query-core/src/environmentManager.ts @@ -24,7 +24,7 @@ export const isServer = (): boolean => isServerFn() * though the environment should behave like a client. * * @example - * ```ts + * ;```ts * import { environmentManager } from '@tanstack/query-core' * * environmentManager.setIsServer(() => false) diff --git a/packages/query-core/src/focusManager.ts b/packages/query-core/src/focusManager.ts index cd7c80942ac..6215f6a1bb0 100644 --- a/packages/query-core/src/focusManager.ts +++ b/packages/query-core/src/focusManager.ts @@ -58,7 +58,7 @@ export class FocusManager extends Subscribable { * notify subscribers. * * @example - * ```ts + * ;```ts * import { focusManager } from '@tanstack/query-core' * * focusManager.setEventListener((handleFocus) => { @@ -96,7 +96,7 @@ export class FocusManager extends Subscribable { * to fall back to the default focus check. * * @example - * ```ts + * ;```ts * import { focusManager } from '@tanstack/query-core' * * // Set focused diff --git a/packages/query-core/src/hydration.ts b/packages/query-core/src/hydration.ts index b9aeaa4fdeb..07cd2908db5 100644 --- a/packages/query-core/src/hydration.ts +++ b/packages/query-core/src/hydration.ts @@ -265,7 +265,7 @@ export function defaultShouldDehydrateQuery(query: Query) { * `defaultShouldDehydrateMutation`. * * @example - * ```ts + * ;```ts * const queryClient = new QueryClient() * * await queryClient.prefetchQuery({ diff --git a/packages/query-core/src/infiniteQueryObserver.ts b/packages/query-core/src/infiniteQueryObserver.ts index 249a4d8fed6..c28471d2e1a 100644 --- a/packages/query-core/src/infiniteQueryObserver.ts +++ b/packages/query-core/src/infiniteQueryObserver.ts @@ -27,7 +27,7 @@ type InfiniteQueryObserverListener = ( * `useInfiniteQuery`) build their hooks on top of. * * @example - * ```ts + * ;```ts * const observer = new InfiniteQueryObserver(queryClient, { * queryKey: ['projects'], * queryFn: ({ pageParam }) => fetchProjects(pageParam), @@ -152,7 +152,7 @@ export class InfiniteQueryObserver< * current pages/page params and whose result also determines `hasNextPage`. * * @example - * ```ts + * ;```ts * const { hasNextPage } = observer.getCurrentResult() * * if (hasNextPage) { @@ -187,7 +187,7 @@ export class InfiniteQueryObserver< * `hasPreviousPage`. * * @example - * ```ts + * ;```ts * const { hasPreviousPage } = observer.getCurrentResult() * * if (hasPreviousPage) { diff --git a/packages/query-core/src/mutation.ts b/packages/query-core/src/mutation.ts index 82fa49aef53..85c6879eb7a 100644 --- a/packages/query-core/src/mutation.ts +++ b/packages/query-core/src/mutation.ts @@ -123,7 +123,7 @@ export type Action = * possible via `mutationCache.find()`/`getAll()` for inspecting cache state. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) @@ -248,7 +248,7 @@ export class Mutation< * without running anything again. * * @example - * ```ts + * ;```ts * // typically driven by reconnect handling, e.g. queryClient.resumePausedMutations() * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) * await mutation?.continue() diff --git a/packages/query-core/src/mutationCache.ts b/packages/query-core/src/mutationCache.ts index 6013d6f4555..8f71dc2e3bd 100644 --- a/packages/query-core/src/mutationCache.ts +++ b/packages/query-core/src/mutationCache.ts @@ -121,7 +121,7 @@ type MutationCacheListener = (event: MutationCacheNotifyEvent) => void * added, removed, or updated. * * @example - * ```ts + * ;```ts * const unsubscribe = mutationCache.subscribe((event) => { * console.log(event.type, event.mutation) * }) @@ -146,7 +146,7 @@ export class MutationCache extends Subscribable { * options. * @param options - The mutation options. They are defaulted with * {@link - * QueryClient#defaultMutationOptions}. + * QueryClient#defaultMutationOptions}. * @param state - The initial state of the mutation, e.g. when restoring a * dehydrated mutation. * @returns The new mutation, already added to the cache. @@ -272,7 +272,7 @@ export class MutationCache extends Subscribable { * Removes all mutations from the cache. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * mutationCache.clear() @@ -296,7 +296,7 @@ export class MutationCache extends Subscribable { * when needing more information about a mutation in rare scenarios. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * const mutations = mutationCache.getAll() @@ -317,7 +317,7 @@ export class MutationCache extends Subscribable { * when needing more information about a mutation in rare scenarios. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * const mutation = mutationCache.find({ mutationKey: ['addPost'] }) @@ -351,7 +351,7 @@ export class MutationCache extends Subscribable { * when needing more information about mutations in rare scenarios. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * const mutations = mutationCache.findAll({ mutationKey: ['addPost'] }) diff --git a/packages/query-core/src/mutationObserver.ts b/packages/query-core/src/mutationObserver.ts index 7c8265877ca..be217139af5 100644 --- a/packages/query-core/src/mutationObserver.ts +++ b/packages/query-core/src/mutationObserver.ts @@ -29,7 +29,7 @@ type MutationObserverListener = ( * a new underlying `Mutation` in the `MutationCache` and executes it. * * @example - * ```ts + * ;```ts * const observer = new MutationObserver(queryClient, { * mutationFn: (variables: { title: string }) => addPost(variables), * }) @@ -90,7 +90,7 @@ export class MutationObserver< * `pending`, its options are updated in place as well. * * @example - * ```ts + * ;```ts * observer.setOptions({ * mutationFn: (variables: { title: string }) => addPost(variables), * onSuccess: (data) => console.log(data), @@ -99,7 +99,7 @@ export class MutationObserver< * * @param options - The new mutation observer options. They are defaulted with * {@link - * QueryClient#defaultMutationOptions} before being applied. + * QueryClient#defaultMutationOptions} before being applied. */ setOptions( options: MutationObserverOptions< @@ -188,7 +188,7 @@ export class MutationObserver< * brand new mutation. * * @example - * ```ts + * ;```ts * observer.reset() * ``` * @@ -213,7 +213,7 @@ export class MutationObserver< * the observer's own options. * * @example - * ```ts + * ;```ts * await observer.mutate( * { title: 'New post' }, * { onSuccess: (data) => console.log(data) }, diff --git a/packages/query-core/src/notifyManager.ts b/packages/query-core/src/notifyManager.ts index 2a9843f03ca..69cee5ac12e 100644 --- a/packages/query-core/src/notifyManager.ts +++ b/packages/query-core/src/notifyManager.ts @@ -120,7 +120,7 @@ export function createNotifyManager() { * re-render instead of one per subscriber. * * @example - * ```ts + * ;```ts * import { notifyManager } from '@tanstack/query-core' * import { batch } from 'solid-js' * @@ -138,7 +138,7 @@ export function createNotifyManager() { * default behavior is `setTimeout(callback, 0)`. * * @example - * ```ts + * ;```ts * import { notifyManager } from '@tanstack/query-core' * * // Schedule batches in the next microtask diff --git a/packages/query-core/src/onlineManager.ts b/packages/query-core/src/onlineManager.ts index 184801fedb7..fff94930941 100644 --- a/packages/query-core/src/onlineManager.ts +++ b/packages/query-core/src/onlineManager.ts @@ -61,7 +61,7 @@ export class OnlineManager extends Subscribable { * online state changes. * * @example - * ```ts + * ;```ts * import NetInfo from '@react-native-community/netinfo' * import { onlineManager } from '@tanstack/query-core' * @@ -86,7 +86,7 @@ export class OnlineManager extends Subscribable { * `setOnline` can be used to manually set the online state. * * @example - * ```ts + * ;```ts * import { onlineManager } from '@tanstack/query-core' * * // Set to online diff --git a/packages/query-core/src/queriesObserver.ts b/packages/query-core/src/queriesObserver.ts index 69a05b5166a..dbd2c33da54 100644 --- a/packages/query-core/src/queriesObserver.ts +++ b/packages/query-core/src/queriesObserver.ts @@ -50,7 +50,7 @@ export interface QueriesObserverOptions< * `useQueries`) build their hooks on top of. * * @example - * ```ts + * ;```ts * const observer = new QueriesObserver(queryClient, [ * { queryKey: ['post', 1], queryFn: fetchPost }, * { queryKey: ['post', 2], queryFn: fetchPost }, @@ -125,7 +125,7 @@ export class QueriesObserver< * created and subscribed to for newly added queries. * * @example - * ```ts + * ;```ts * observer.setQueries([ * { queryKey: ['post', 1], queryFn: fetchPost }, * { queryKey: ['post', 3], queryFn: fetchPost }, @@ -214,7 +214,7 @@ export class QueriesObserver< * or `setQueries`. * * @example - * ```ts + * ;```ts * const results = observer.getCurrentResult() * const data = results.map((result) => result.data) * ``` diff --git a/packages/query-core/src/query.ts b/packages/query-core/src/query.ts index e8998a77359..a370ee870c0 100644 --- a/packages/query-core/src/query.ts +++ b/packages/query-core/src/query.ts @@ -267,7 +267,7 @@ export type Action = * possible via `queryCache.find()`/`findAll()` for inspecting cache state. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * const query = queryCache.find({ queryKey: ['posts'] }) * @@ -425,7 +425,7 @@ export class Query< * - If no fetch is in progress, resolves immediately. * * @example - * ```ts + * ;```ts * await query.cancel() * ``` * @@ -542,7 +542,7 @@ export class Query< * or has been invalidated. * * @example - * ```ts + * ;```ts * if (query.isStale()) { * // refetch or otherwise treat the cached data as outdated * } @@ -573,7 +573,7 @@ export class Query< * - Otherwise, staleness is based on elapsed time since `dataUpdatedAt`. * * @example - * ```ts + * ;```ts * const isStale = query.isStaleByTime(1000 * 60) * ``` * @@ -688,7 +688,7 @@ export class Query< * Returns the number of observers currently subscribed to this query. * * @example - * ```ts + * ;```ts * if (query.getObserversCount() === 0) { * // no component is currently watching this query * } @@ -706,7 +706,7 @@ export class Query< * itself trigger a refetch. * * @example - * ```ts + * ;```ts * query.invalidate() * ``` */ diff --git a/packages/query-core/src/queryCache.ts b/packages/query-core/src/queryCache.ts index ae83ade7c9c..9fda79fd4d7 100644 --- a/packages/query-core/src/queryCache.ts +++ b/packages/query-core/src/queryCache.ts @@ -126,7 +126,7 @@ export interface QueryStore { * directly) do not notify subscribers. * * @example - * ```ts + * ;```ts * const unsubscribe = queryCache.subscribe((event) => { * console.log(event.type, event.query) * }) @@ -148,7 +148,7 @@ export class QueryCache extends Subscribable { * bypassing the reactive `QueryObserver` machinery. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * const query = queryCache.build(queryClient, { @@ -225,7 +225,7 @@ export class QueryCache extends Subscribable { * `QueryCache` instances. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * const query = queryCache.find({ queryKey: ['posts'] }) * @@ -250,7 +250,7 @@ export class QueryCache extends Subscribable { * Removes all queries from the cache. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * queryCache.clear() @@ -271,7 +271,7 @@ export class QueryCache extends Subscribable { * (e.g. broadcast/hydration) that already have a hash to look up directly. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * const queryHash = hashKey(['posts']) * @@ -298,7 +298,7 @@ export class QueryCache extends Subscribable { * Returns all queries within the cache. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * const queries = queryCache.getAll() @@ -322,7 +322,7 @@ export class QueryCache extends Subscribable { * be used as an initial value). * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * const query = queryCache.find({ queryKey: ['posts'] }) @@ -352,7 +352,7 @@ export class QueryCache extends Subscribable { * when needing more information about queries in rare scenarios. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * const queries = queryCache.findAll({ queryKey: ['posts'] }) diff --git a/packages/query-core/src/queryClient.ts b/packages/query-core/src/queryClient.ts index 21f7f258fb6..5e15c80c0b1 100644 --- a/packages/query-core/src/queryClient.ts +++ b/packages/query-core/src/queryClient.ts @@ -65,7 +65,7 @@ interface MutationDefaults { * mutations created through it. * * @example - * ```ts + * ;```ts * const queryClient = new QueryClient({ * defaultOptions: { * queries: { @@ -143,7 +143,7 @@ export class QueryClient { * loading new pages, and loading more infinite query results. * * @example - * ```ts + * ;```ts * if (queryClient.isFetching()) { * console.log('At least one query is fetching!') * } @@ -166,7 +166,7 @@ export class QueryClient { * optionally matching a set of filters. * * @example - * ```ts + * ;```ts * if (queryClient.isMutating()) { * console.log('At least one mutation is pending!') * } @@ -260,7 +260,7 @@ export class QueryClient { * contents. * * @example - * ```ts + * ;```ts * const data = queryClient.getQueriesData({ queryKey: ['posts'] }) * ``` * @@ -290,7 +290,7 @@ export class QueryClient { * previously retrieved via {@link QueryClient#getQueryData}, in place. * * @example - * ```ts + * ;```ts * queryClient.setQueryData(['posts'], newPosts) * * // Or, using an updater function that receives the current data: @@ -349,7 +349,7 @@ export class QueryClient { * matching query. * * @example - * ```ts + * ;```ts * queryClient.setQueriesData({ queryKey: ['posts'] }, (oldPosts) => * oldPosts ? oldPosts.filter((post) => post.id !== deletedId) : oldPosts, * ) @@ -390,7 +390,7 @@ export class QueryClient { * query does not exist, `undefined` is returned. * * @example - * ```ts + * ;```ts * const state = queryClient.getQueryState(['posts']) * console.log(state?.dataUpdatedAt) * ``` @@ -421,7 +421,7 @@ export class QueryClient { * Without filters, every query in the cache is removed. * * @example - * ```ts + * ;```ts * queryClient.removeQueries({ queryKey: ['posts'], exact: true }) * ``` * @@ -446,7 +446,7 @@ export class QueryClient { * resolves once that refetch settles. * * @example - * ```ts + * ;```ts * await queryClient.resetQueries({ queryKey: ['posts'], exact: true }) * ``` * @@ -489,7 +489,7 @@ export class QueryClient { * The returned promise never rejects, even if individual cancellations fail. * * @example - * ```ts + * ;```ts * await queryClient.cancelQueries({ queryKey: ['posts'], exact: true }) * ``` * @@ -524,7 +524,7 @@ export class QueryClient { * `'active'`. * * @example - * ```ts + * ;```ts * await queryClient.invalidateQueries({ * queryKey: ['posts'], * refetchType: 'active', @@ -573,7 +573,7 @@ export class QueryClient { * unless `throwOnError` is set. * * @example - * ```ts + * ;```ts * // refetch all active queries partially matching a query key: * await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' }) * ``` @@ -636,7 +636,7 @@ export class QueryClient { * staleTime: 'static' }` — the deprecated `ensureQueryData`. * * @example - * ```ts + * ;```ts * try { * const data = await queryClient.query({ * queryKey, @@ -774,7 +774,7 @@ export class QueryClient { * with `{ staleTime: 'static' }` — the deprecated `ensureInfiniteQueryData`. * * @example - * ```ts + * ;```ts * try { * const data = await queryClient.infiniteQuery({ * queryKey, @@ -916,7 +916,7 @@ export class QueryClient { * Does nothing (resolving immediately) if the client is currently offline. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() @@ -936,7 +936,7 @@ export class QueryClient { * Returns the query cache this client is connected to. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() @@ -954,7 +954,7 @@ export class QueryClient { * Returns the mutation cache this client is connected to. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() @@ -973,7 +973,7 @@ export class QueryClient { * {@link QueryClient#setDefaultOptions}. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() @@ -991,7 +991,7 @@ export class QueryClient { * previously defined default options. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() @@ -1020,7 +1020,7 @@ export class QueryClient { * registered after more generic ones so they take precedence. * * @example - * ```ts + * ;```ts * queryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts }) * * await queryClient.query({ queryKey: ['posts'] }) @@ -1057,7 +1057,7 @@ export class QueryClient { * they are merged together in registration order. * * @example - * ```ts + * ;```ts * const defaultOptions = queryClient.getQueryDefaults(['posts']) * ``` * @@ -1090,7 +1090,7 @@ export class QueryClient { * mutation key. * * @example - * ```ts + * ;```ts * queryClient.setMutationDefaults(['addPost'], { mutationFn: addPost }) * ``` * @@ -1124,7 +1124,7 @@ export class QueryClient { * match, they are merged together in registration order. * * @example - * ```ts + * ;```ts * const defaultOptions = queryClient.getMutationDefaults(['addPost']) * ``` * @@ -1273,7 +1273,7 @@ export class QueryClient { * to. * * @example - * ```ts + * ;```ts * import { QueryClient } from '@tanstack/query-core' * * const queryClient = new QueryClient() diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts index 3391a7aac21..9055f14cf28 100644 --- a/packages/query-core/src/queryObserver.ts +++ b/packages/query-core/src/queryObserver.ts @@ -43,7 +43,7 @@ interface ObserverFetchOptions extends FetchOptions { * outside of any framework. * * @example - * ```ts + * ;```ts * const observer = new QueryObserver(queryClient, { * queryKey: ['posts'], * queryFn: fetchPosts, @@ -181,7 +181,7 @@ export class QueryObserver< * refetch-interval timers as needed. * * @example - * ```ts + * ;```ts * observer.setOptions({ * queryKey: ['posts', 1], * queryFn: () => fetchPost(1), @@ -195,7 +195,7 @@ export class QueryObserver< * * @param options - The new observer options. They are defaulted with * {@link - * QueryClient#defaultQueryOptions} before being applied. + * QueryClient#defaultQueryOptions} before being applied. * @throws {Error} If `enabled` is neither a boolean nor a function. */ setOptions( @@ -337,7 +337,7 @@ export class QueryObserver< * method). * * @example - * ```ts + * ;```ts * const result = observer.getCurrentResult() * console.log(result.status, result.data) * ``` @@ -400,7 +400,7 @@ export class QueryObserver< * resulting `QueryObserverResult`. * * @example - * ```ts + * ;```ts * const result = await observer.refetch({ cancelRefetch: false }) * console.log(result.data) * ``` @@ -426,7 +426,7 @@ export class QueryObserver< * to) will need, ahead of time. * * @example - * ```ts + * ;```ts * const result = await observer.fetchOptimistic({ * queryKey: ['posts', 2], * queryFn: () => fetchPost(2), diff --git a/packages/query-core/src/retryer.ts b/packages/query-core/src/retryer.ts index d16f58e3db0..93c69b79541 100644 --- a/packages/query-core/src/retryer.ts +++ b/packages/query-core/src/retryer.ts @@ -105,11 +105,11 @@ export function canFetch(networkMode: NetworkMode | undefined): boolean { * query.cancel() * * try { - * await query.promise + * await query.promise * } catch (error) { - * if (error instanceof CancelledError) { - * // the fetch was cancelled, e.g. via `query.cancel()` - * } + * if (error instanceof CancelledError) { + * // the fetch was cancelled, e.g. via `query.cancel()` + * } * } * ``` */ diff --git a/packages/query-core/src/streamedQuery.ts b/packages/query-core/src/streamedQuery.ts index 875a70c08f9..2eb43efc14a 100644 --- a/packages/query-core/src/streamedQuery.ts +++ b/packages/query-core/src/streamedQuery.ts @@ -60,7 +60,7 @@ type StreamedQueryParams = * 'fetching' until the stream ends. * * @example - * ```ts + * ;```ts * await queryClient.query({ * queryKey: ['data'], * queryFn: streamedQuery({ diff --git a/packages/query-core/src/subscribable.ts b/packages/query-core/src/subscribable.ts index b354793fbc3..8b3684c5599 100644 --- a/packages/query-core/src/subscribable.ts +++ b/packages/query-core/src/subscribable.ts @@ -18,7 +18,7 @@ export class Subscribable { * subclasses clear all of theirs in `destroy()`. * * @example - * ```ts + * ;```ts * const unsubscribe = subscribable.subscribe(() => { * // react to the update * }) diff --git a/packages/query-core/src/timeoutManager.ts b/packages/query-core/src/timeoutManager.ts index 147cb67d80d..5fcd9ca39f4 100644 --- a/packages/query-core/src/timeoutManager.ts +++ b/packages/query-core/src/timeoutManager.ts @@ -105,7 +105,7 @@ export class TimeoutManager implements Omit { * others' timers. * * @example - * ```ts + * ;```ts * import { timeoutManager, QueryClient } from '@tanstack/query-core' * import { CustomTimeoutProvider } from './CustomTimeoutProvider' * @@ -154,7 +154,7 @@ export class TimeoutManager implements Omit { * coerced to a number via `Symbol.toPrimitive`. * * @example - * ```ts + * ;```ts * import { timeoutManager } from '@tanstack/query-core' * * const timeoutId = timeoutManager.setTimeout( @@ -182,7 +182,7 @@ export class TimeoutManager implements Omit { * returned by `setTimeout`. * * @example - * ```ts + * ;```ts * import { timeoutManager } from '@tanstack/query-core' * * const timeoutId = timeoutManager.setTimeout( @@ -207,7 +207,7 @@ export class TimeoutManager implements Omit { * object that can be coerced to a number via `Symbol.toPrimitive`. * * @example - * ```ts + * ;```ts * import { timeoutManager } from '@tanstack/query-core' * * const intervalId = timeoutManager.setInterval( @@ -233,7 +233,7 @@ export class TimeoutManager implements Omit { * by `setInterval`. * * @example - * ```ts + * ;```ts * import { timeoutManager } from '@tanstack/query-core' * * const intervalId = timeoutManager.setInterval( diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 33b0cf25837..5efe1000b03 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -65,7 +65,7 @@ export type Override = { * `@tanstack/query-core` works too and covers every adapter at once. * * @example - * ```ts + * ;```ts * // Use the module you installed — here, the React adapter. * declare module '@tanstack/react-query' { * interface Register { diff --git a/packages/query-core/src/utils.ts b/packages/query-core/src/utils.ts index a6bb2180219..d9a944a6986 100644 --- a/packages/query-core/src/utils.ts +++ b/packages/query-core/src/utils.ts @@ -78,7 +78,7 @@ export interface MutationFilters< * the previous data. See {@link functionalUpdate}. * * @example - * ```ts + * ;```ts * queryClient.setQueryData(['posts'], newPosts) * * // Or, using an updater function that receives the current data: @@ -184,7 +184,7 @@ export function resolveQueryValue< * that is specified must match; filters that are left unspecified are ignored. * * @example - * ```ts + * ;```ts * const queryCache = queryClient.getQueryCache() * * const matchingQueries = queryCache @@ -251,7 +251,7 @@ export function matchQuery( * `mutationKey` of its own, it does not match. * * @example - * ```ts + * ;```ts * const mutationCache = queryClient.getMutationCache() * * const matchingMutations = mutationCache @@ -316,7 +316,7 @@ export function hashQueryKeyByOptions( * hash. * * @example - * ```ts + * ;```ts * // Object keys are sorted, so key order doesn't affect the hash: * hashKey(['todos', { page: 1, filter: 'done' }]) // === '["todos",{"filter":"done","page":1}]' * ``` @@ -525,8 +525,8 @@ export function isPlainObject(o: any): o is Record { * Checks whether a value's `Object.prototype.toString` tag is `[object * Object]`. * - * @param o - The value to check. - * @returns `true` if the tag is `[object Object]`. + * @param o - The value to check. @returns `true` if the tag is `[object + * Object]`. */ function hasObjectPrototype(o: any): boolean { return Object.prototype.toString.call(o) === '[object Object]' @@ -590,7 +590,7 @@ export function replaceData< * previously fetched data until the new data arrives. * * @example - * ```ts + * ;```ts * new QueryObserver(queryClient, { * queryKey: ['posts', page], * queryFn: () => fetchPosts(page), @@ -647,7 +647,7 @@ export function addToStart(items: Array, item: T, max = 0): Array { * `skipToken` cannot be triggered with `refetch`. * * @example - * ```ts + * ;```ts * new QueryObserver(queryClient, { * queryKey: ['post', postId], * queryFn: postId != null ? () => fetchPost(postId) : skipToken, @@ -711,7 +711,7 @@ export function ensureQueryFn< * `false`). * * @example - * ```ts + * ;```ts * const throwOnError = * query.state.error && typeof options.throwOnError === 'function' * ? shouldThrowError(options.throwOnError, [query.state.error, query]) diff --git a/packages/react-query/src/HydrationBoundary.tsx b/packages/react-query/src/HydrationBoundary.tsx index 543c278d39e..568bb44f5b1 100644 --- a/packages/react-query/src/HydrationBoundary.tsx +++ b/packages/react-query/src/HydrationBoundary.tsx @@ -45,7 +45,7 @@ export interface HydrationBoundaryProps { * Note: Only `queries` can be dehydrated with an `HydrationBoundary`. * * @example - * ```tsx + * ;```tsx * import { HydrationBoundary } from '@tanstack/react-query' * * function App() { diff --git a/packages/react-query/src/QueryClientProvider.tsx b/packages/react-query/src/QueryClientProvider.tsx index 9ef8248a39d..b1ad4f25558 100644 --- a/packages/react-query/src/QueryClientProvider.tsx +++ b/packages/react-query/src/QueryClientProvider.tsx @@ -54,7 +54,7 @@ export type QueryClientProviderProps = { * and refetching as needed when the app regains focus or comes back online). * * @example - * ```tsx + * ;```tsx * import { QueryClient, QueryClientProvider } from '@tanstack/react-query' * * const queryClient = new QueryClient() diff --git a/packages/react-query/src/QueryErrorResetBoundary.tsx b/packages/react-query/src/QueryErrorResetBoundary.tsx index 9b57cad375e..80f91ee5ee6 100644 --- a/packages/react-query/src/QueryErrorResetBoundary.tsx +++ b/packages/react-query/src/QueryErrorResetBoundary.tsx @@ -81,7 +81,7 @@ const QueryErrorResetBoundaryContext = React.createContext(createValue()) * globally. * * @example - * ```tsx + * ;```tsx * import { ErrorBoundary } from 'react-error-boundary' * import { useQueryErrorResetBoundary } from '@tanstack/react-query' * @@ -137,7 +137,7 @@ export interface QueryErrorResetBoundaryProps { * any query errors within the boundaries of the component. * * @example - * ```tsx + * ;```tsx * import { ErrorBoundary } from 'react-error-boundary' * import { QueryErrorResetBoundary } from '@tanstack/react-query' * diff --git a/packages/react-query/src/infiniteQueryOptions.ts b/packages/react-query/src/infiniteQueryOptions.ts index f192694eece..92fbd416366 100644 --- a/packages/react-query/src/infiniteQueryOptions.ts +++ b/packages/react-query/src/infiniteQueryOptions.ts @@ -156,33 +156,33 @@ export type DefinedInitialDataInfiniteOptions< * @example * ```tsx * import { - * infiniteQueryOptions, - * useInfiniteQuery, + * infiniteQueryOptions, + * useInfiniteQuery, * } from '@tanstack/react-query' * * export const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, * }) * * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery(projectsOptions) + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery(projectsOptions) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => - * page.projects.map((p) =>
  • {p.name}
  • ), - * )} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) * } * ``` * diff --git a/packages/react-query/src/mutationOptions.ts b/packages/react-query/src/mutationOptions.ts index fb41844e545..fe5059f2014 100644 --- a/packages/react-query/src/mutationOptions.ts +++ b/packages/react-query/src/mutationOptions.ts @@ -55,7 +55,7 @@ export function mutationOptions< * See the other overload's example for looking a mutation up via * `useMutationState`. * @example - * ```tsx + * ;```tsx * import { mutationOptions, useMutation } from '@tanstack/react-query' * * export const createPostOptions = mutationOptions({ diff --git a/packages/react-query/src/queryOptions.ts b/packages/react-query/src/queryOptions.ts index efecd11efb3..9eb11618261 100644 --- a/packages/react-query/src/queryOptions.ts +++ b/packages/react-query/src/queryOptions.ts @@ -125,26 +125,26 @@ export type DefinedInitialDataOptions< * import { queryOptions, useQuery } from '@tanstack/react-query' * * export const postsOptions = queryOptions({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], * }) * * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery(postsOptions) + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery(postsOptions) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) * } * ``` * diff --git a/packages/react-query/src/useInfiniteQuery.ts b/packages/react-query/src/useInfiniteQuery.ts index 834aba9322b..7fe4d1c713d 100644 --- a/packages/react-query/src/useInfiniteQuery.ts +++ b/packages/react-query/src/useInfiniteQuery.ts @@ -35,26 +35,26 @@ import type { * import { useInfiniteQuery } from '@tanstack/react-query' * * function Projects() { - * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const { data, isError, error } = useInfiniteQuery({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * }) - * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.pages.map((page) => - * page.projects.map((p) =>
  • {p.name}
  • ), - * )} - *
- *
- * ) + * // `data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const { data, isError, error } = useInfiniteQuery({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, + * }) + * + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.pages.map((page) => + * page.projects.map((p) =>
  • {p.name}
  • ), + * )} + *
+ *
+ * ) * } * ``` * diff --git a/packages/react-query/src/useIsFetching.ts b/packages/react-query/src/useIsFetching.ts index 9725b3f3885..8f63a5cde75 100644 --- a/packages/react-query/src/useIsFetching.ts +++ b/packages/react-query/src/useIsFetching.ts @@ -11,7 +11,7 @@ import type { QueryClient, QueryFilters } from '@tanstack/query-core' * loading indicators). * * @example - * ```tsx + * ;```tsx * import { useIsFetching } from '@tanstack/react-query' * * function PostsFetchingIndicator() { diff --git a/packages/react-query/src/useMutation.ts b/packages/react-query/src/useMutation.ts index c0aaf5ccffa..b644a70aaa0 100644 --- a/packages/react-query/src/useMutation.ts +++ b/packages/react-query/src/useMutation.ts @@ -21,7 +21,7 @@ import type { DefaultError, QueryClient } from '@tanstack/query-core' * perform server side-effects. `useMutation` is the hook for that. * * @example - * ```tsx + * ;```tsx * import { useMutation, useQueryClient } from '@tanstack/react-query' * * function AddTodo() { diff --git a/packages/react-query/src/useMutationState.ts b/packages/react-query/src/useMutationState.ts index 14b1d53b681..f5006802877 100644 --- a/packages/react-query/src/useMutationState.ts +++ b/packages/react-query/src/useMutationState.ts @@ -17,7 +17,7 @@ import type { * indicators). * * @example - * ```tsx + * ;```tsx * import { useIsMutating } from '@tanstack/react-query' * * function PostsMutatingIndicator() { diff --git a/packages/react-query/src/usePrefetchInfiniteQuery.tsx b/packages/react-query/src/usePrefetchInfiniteQuery.tsx index e3b9b631efd..0af5939f545 100644 --- a/packages/react-query/src/usePrefetchInfiniteQuery.tsx +++ b/packages/react-query/src/usePrefetchInfiniteQuery.tsx @@ -30,7 +30,7 @@ import type { UsePrefetchInfiniteQueryOptions } from './types' * already in flight. * * @example - * ```tsx + * ;```tsx * import { Suspense } from 'react' * import { * infiniteQueryOptions, diff --git a/packages/react-query/src/usePrefetchQuery.tsx b/packages/react-query/src/usePrefetchQuery.tsx index 56bb1b73b77..b7af343b987 100644 --- a/packages/react-query/src/usePrefetchQuery.tsx +++ b/packages/react-query/src/usePrefetchQuery.tsx @@ -18,7 +18,7 @@ import type { UsePrefetchQueryOptions } from './types' * already in flight. * * @example - * ```tsx + * ;```tsx * import { Suspense } from 'react' * import { usePrefetchQuery } from '@tanstack/react-query' * diff --git a/packages/react-query/src/useQueries.ts b/packages/react-query/src/useQueries.ts index fcfe8d5dce2..cbf7c7ec6cd 100644 --- a/packages/react-query/src/useQueries.ts +++ b/packages/react-query/src/useQueries.ts @@ -268,7 +268,7 @@ export type QueriesResults< * from previously rendered queries, because the number of queries can differ * between renders. * @example - * ```tsx + * ;```tsx * import { useQueries } from '@tanstack/react-query' * * function Posts({ ids }: { ids: Array }) { diff --git a/packages/react-query/src/useQuery.ts b/packages/react-query/src/useQuery.ts index 2eb171fe488..fbb09d2d307 100644 --- a/packages/react-query/src/useQuery.ts +++ b/packages/react-query/src/useQuery.ts @@ -22,24 +22,24 @@ import type { * import { useQuery } from '@tanstack/react-query' * * function Posts() { - * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const { data, isError, error } = useQuery({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * }) + * // `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const { data, isError, error } = useQuery({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * }) * - * return ( - *
- * {isError ? Error: {error.message} : null} - *
    - * {data.map((post) => ( - *
  • {post.title}
  • - * ))} - *
- *
- * ) + * return ( + *
+ * {isError ? Error: {error.message} : null} + *
    + * {data.map((post) => ( + *
  • {post.title}
  • + * ))} + *
+ *
+ * ) * } * ``` * @@ -69,7 +69,7 @@ export function useQuery< * `undefined`, so the resulting `data` can be `undefined`. * * @example - * ```tsx + * ;```tsx * import { useQuery } from '@tanstack/react-query' * * function Posts() { @@ -143,7 +143,7 @@ export function useQuery< * infer whether `data` can be `undefined` from `initialData` directly. * * @example - * ```tsx + * ;```tsx * import { useQuery } from '@tanstack/react-query' * * function Posts() { diff --git a/packages/solid-query/src/QueryClientProvider.tsx b/packages/solid-query/src/QueryClientProvider.tsx index a636d76b786..5f09ceb540e 100644 --- a/packages/solid-query/src/QueryClientProvider.tsx +++ b/packages/solid-query/src/QueryClientProvider.tsx @@ -87,7 +87,7 @@ export type QueryClientProviderProps = { * and refetching as needed when the app regains focus or comes back online). * * @example - * ```tsx + * ;```tsx * import { QueryClient, QueryClientProvider } from '@tanstack/solid-query' * * const queryClient = new QueryClient() diff --git a/packages/solid-query/src/infiniteQueryOptions.ts b/packages/solid-query/src/infiniteQueryOptions.ts index bdfbddb6ee2..73343ff3622 100644 --- a/packages/solid-query/src/infiniteQueryOptions.ts +++ b/packages/solid-query/src/infiniteQueryOptions.ts @@ -81,37 +81,37 @@ export type DefinedInitialDataInfiniteOptions< * ```tsx * import { For } from 'solid-js' * import { - * infiniteQueryOptions, - * useInfiniteQuery, + * infiniteQueryOptions, + * useInfiniteQuery, * } from '@tanstack/solid-query' * * const projectsOptions = infiniteQueryOptions({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, * }) * * function Projects() { - * // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const projectsQuery = useInfiniteQuery(() => projectsOptions) + * // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const projectsQuery = useInfiniteQuery(() => projectsOptions) * - * return ( - *
- * {projectsQuery.isError ? ( - * Error: {projectsQuery.error.message} - * ) : null} - *
    - * - * {(page) => ( - * {(p) =>
  • {p.name}
  • }
    - * )} - *
    - *
- *
- * ) + * return ( + *
+ * {projectsQuery.isError ? ( + * Error: {projectsQuery.error.message} + * ) : null} + *
    + * + * {(page) => ( + * {(p) =>
  • {p.name}
  • }
    + * )} + *
    + *
+ *
+ * ) * } * ``` * diff --git a/packages/solid-query/src/mutationOptions.ts b/packages/solid-query/src/mutationOptions.ts index ab9afead18c..53ecf69a355 100644 --- a/packages/solid-query/src/mutationOptions.ts +++ b/packages/solid-query/src/mutationOptions.ts @@ -55,7 +55,7 @@ export function mutationOptions< * See the other overload's example for looking a mutation up via * `useMutationState`. * @example - * ```tsx + * ;```tsx * import { mutationOptions, useMutation } from '@tanstack/solid-query' * * const createPostOptions = mutationOptions({ diff --git a/packages/solid-query/src/queryOptions.ts b/packages/solid-query/src/queryOptions.ts index ed1e5c5eeee..a9fc8cc3e40 100644 --- a/packages/solid-query/src/queryOptions.ts +++ b/packages/solid-query/src/queryOptions.ts @@ -67,26 +67,26 @@ export type DefinedInitialDataOptions< * import { queryOptions, useQuery } from '@tanstack/solid-query' * * const postsOptions = queryOptions({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], * }) * * function Posts() { - * // `postsQuery.data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, - * // so the list stays visible alongside the error. - * const postsQuery = useQuery(() => postsOptions) + * // `postsQuery.data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails, + * // so the list stays visible alongside the error. + * const postsQuery = useQuery(() => postsOptions) * - * return ( - *
- * {postsQuery.isError ? ( - * Error: {postsQuery.error.message} - * ) : null} - *
    - * {(post) =>
  • {post.title}
  • }
    - *
- *
- * ) + * return ( + *
+ * {postsQuery.isError ? ( + * Error: {postsQuery.error.message} + * ) : null} + *
    + * {(post) =>
  • {post.title}
  • }
    + *
+ *
+ * ) * } * ``` * diff --git a/packages/solid-query/src/useInfiniteQuery.ts b/packages/solid-query/src/useInfiniteQuery.ts index 3bd8ac0b2b3..a6afb2e96f8 100644 --- a/packages/solid-query/src/useInfiniteQuery.ts +++ b/packages/solid-query/src/useInfiniteQuery.ts @@ -37,30 +37,30 @@ import type { * import { useInfiniteQuery } from '@tanstack/solid-query' * * function Projects() { - * // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const projectsQuery = useInfiniteQuery(() => ({ - * queryKey: ['projects'], - * queryFn: ({ pageParam }) => fetchProjects(pageParam), - * initialPageParam: 0, - * getNextPageParam: (lastPage) => lastPage.nextId, - * initialData: { pages: [], pageParams: [] }, - * })) - * - * return ( - *
- * {projectsQuery.isError ? ( - * Error: {projectsQuery.error.message} - * ) : null} - *
    - * - * {(page) => ( - * {(p) =>
  • {p.name}
  • }
    - * )} - *
    - *
- *
- * ) + * // `projectsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const projectsQuery = useInfiniteQuery(() => ({ + * queryKey: ['projects'], + * queryFn: ({ pageParam }) => fetchProjects(pageParam), + * initialPageParam: 0, + * getNextPageParam: (lastPage) => lastPage.nextId, + * initialData: { pages: [], pageParams: [] }, + * })) + * + * return ( + *
+ * {projectsQuery.isError ? ( + * Error: {projectsQuery.error.message} + * ) : null} + *
    + * + * {(page) => ( + * {(p) =>
  • {p.name}
  • }
    + * )} + *
    + *
+ *
+ * ) * } * ``` * diff --git a/packages/solid-query/src/useIsFetching.ts b/packages/solid-query/src/useIsFetching.ts index ce18289a0f1..c71a4199239 100644 --- a/packages/solid-query/src/useIsFetching.ts +++ b/packages/solid-query/src/useIsFetching.ts @@ -10,7 +10,7 @@ import type { Accessor } from 'solid-js' * loading indicators). * * @example - * ```tsx + * ;```tsx * import { useIsFetching } from '@tanstack/solid-query' * * function GlobalLoadingIndicator() { diff --git a/packages/solid-query/src/useIsMutating.ts b/packages/solid-query/src/useIsMutating.ts index 562d262beb9..b0ff0b06bb7 100644 --- a/packages/solid-query/src/useIsMutating.ts +++ b/packages/solid-query/src/useIsMutating.ts @@ -10,7 +10,7 @@ import type { Accessor } from 'solid-js' * indicators). * * @example - * ```tsx + * ;```tsx * import { useIsMutating } from '@tanstack/solid-query' * * function PostsMutatingIndicator() { diff --git a/packages/solid-query/src/useMutation.ts b/packages/solid-query/src/useMutation.ts index 0b489cf4024..f2544858dc9 100644 --- a/packages/solid-query/src/useMutation.ts +++ b/packages/solid-query/src/useMutation.ts @@ -16,7 +16,7 @@ import type { Accessor } from 'solid-js' * perform server side-effects. `useMutation` is the primitive for that. * * @example - * ```tsx + * ;```tsx * import { useMutation, useQueryClient } from '@tanstack/solid-query' * * function TodoItem(props: { id: number }) { diff --git a/packages/solid-query/src/useQueries.ts b/packages/solid-query/src/useQueries.ts index b48d1b47c5b..dc5035ec260 100644 --- a/packages/solid-query/src/useQueries.ts +++ b/packages/solid-query/src/useQueries.ts @@ -205,7 +205,7 @@ type QueriesResults< * queries can differ between renders. * * @example - * ```tsx + * ;```tsx * import { For } from 'solid-js' * import { useQueries } from '@tanstack/solid-query' * diff --git a/packages/solid-query/src/useQuery.ts b/packages/solid-query/src/useQuery.ts index 1a42d396c62..42cbd92d2d4 100644 --- a/packages/solid-query/src/useQuery.ts +++ b/packages/solid-query/src/useQuery.ts @@ -20,7 +20,7 @@ import type { * it — `enabled: false` skips the initial fetch. * * @example - * ```tsx + * ;```tsx * import { For, Match, Switch } from 'solid-js' * import { useQuery } from '@tanstack/solid-query' * @@ -214,24 +214,24 @@ export function useQuery< * import { useQuery } from '@tanstack/solid-query' * * function Posts() { - * // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const postsQuery = useQuery(() => ({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * })) + * // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const postsQuery = useQuery(() => ({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * })) * - * return ( - *
- * {postsQuery.isError ? ( - * Error: {postsQuery.error.message} - * ) : null} - *
    - * {(post) =>
  • {post.title}
  • }
    - *
- *
- * ) + * return ( + *
+ * {postsQuery.isError ? ( + * Error: {postsQuery.error.message} + * ) : null} + *
    + * {(post) =>
  • {post.title}
  • }
    + *
+ *
+ * ) * } * ``` * diff --git a/packages/svelte-query/src/context.ts b/packages/svelte-query/src/context.ts index 3dfff7a9c0f..9198d0c31df 100644 --- a/packages/svelte-query/src/context.ts +++ b/packages/svelte-query/src/context.ts @@ -31,7 +31,7 @@ export const getQueryClientContext = (): QueryClient => { * need to set the client from your own component instead. * * @example - * ```svelte + * ;```svelte * - * ``` + * @example Looking the mutation up elsewhere via its `mutationKey`, e.g. for a + * global "saving…" indicator: + * + * ```vue + * + * ``` * * @param options - The mutation options to use, identical to what you'd pass to - * `useMutation`, with a required `mutationKey`. - * @returns The same options object, unchanged. - * @see {@link useMutation} to run the mutation these options describe. + * `useMutation`, with a required `mutationKey`. @returns The same options + * object, unchanged. @see {@link useMutation} to run the mutation these options + * describe. */ export function mutationOptions< TData = unknown, @@ -111,7 +112,7 @@ export function mutationOptions< * See the other overload's example for looking a mutation up via * `useMutationState`. * @example - * ```vue + * ;```vue *