import { AxiosError } from 'axios'; import type { QueryInvalidationOptions } from '../types/query-invalidation-options'; import type { GlobalClientOptions } from './client-helpers'; import { QueryClientStore } from './query-client.store'; import type { QueryKey, QueryObserverOptions, QueryObserverResult } from '@tanstack/query-core'; /** * Optional interface for the `QueryApiStore` inheritance pattern. * Not needed for the composable `@queryStore` decorator approach — use the * `refreshOnMount()` factory from `@servicetitan/tanstack-query-mobx/composable` instead. * * @remarks * Allows stores to automatically refresh stale data when navigating between components. * {@link QueryApi} and {@link QueryApiStore} implement this interface. * Implementing it in your own store is optional — only needed if you want to * participate in the `storesToRefreshOnMount` chain. * * @see `refreshOnMount()` factory for the composable approach (recommended) */ export interface IRefreshOnMountStore { /** Triggers refresh for all registered dependent stores */ refreshStoresOnMount: () => void; /** Refreshes this store if data is stale */ refreshOnMount: () => void; /** Optional list of dependent stores to refresh on mount */ storesToRefreshOnMount?: () => (IRefreshOnMountStore | undefined)[]; } /** * Configuration options for queries, extending TanStack Query's QueryObserverOptions * with additional integration-specific options. * * @template T - The type of data returned by the query * @template TError - The error type (default: AxiosError) * * @remarks * Extends TanStack Query's standard query options with MobX integration features. * All standard options (queryKey, queryFn, staleTime, enabled, etc.) are available. * Default `staleTime` is 10 minutes (set by `QueryClientStore`). Override per-query as needed. * * @see [TanStack Query QueryOptions](https://tanstack.com/query/latest/docs/framework/react/reference/useQuery) * @see {@link QueryApi} for the query manager that uses these options * @see README.md "Key Concepts" and "Common Patterns" for usage examples * * @example Basic query configuration * ```typescript * get queryOptions(): QueryApiOptions { * return { * queryKey: ['scheduling', 'jobs'], * queryFn: async () => (await this.api?.getJobs())?.data ?? [], * staleTime: 5 * 60 * 1000, // 5 minutes * }; * } * ``` * * @example Data-driven query with dependencies * ```typescript * get queryOptions(): QueryApiOptions { * return { * queryKey: ['scheduling', 'job', this.jobId], // Refetches when jobId changes * queryFn: async () => (await this.api?.getJob(this.jobId))?.data, * enabled: this.jobId > 0, // Only fetch when jobId is valid * }; * } * ``` */ export interface QueryApiOptions extends QueryObserverOptions { /** * Remove the query from the client cache when disposed (default: false). * Useful for queries with sensitive data or very dynamic content. * * - `true`: removes cache using the full query key * - `number`: removes cache using the first N segments of the query key * * @example * ```typescript * disposeQuery: true // Remove exact query from cache when store unmounts * disposeQuery: 2 // Remove all queries matching the first 2 key segments * ``` */ disposeQuery?: boolean | number; /** * Automatically set initialized to true after successful fetch (default: true). * Set to false if you need manual control over initialization state. * * @see {@link QueryApi.initialized} */ autoInitialize?: boolean; /** * Callback invoked when query succeeds with the result data. * * @example * ```typescript * onSuccess: (data) => { * console.log('Loaded', data.length, 'jobs'); * this.processData(data); * } * ``` */ onSuccess?: (data: T) => void; /** * Callback invoked when query fails with the error object. * If not provided, errors are logged to console. * * @example * ```typescript * onError: (error) => { * console.error('Failed to load jobs:', error); * showNotification('Failed to load data'); * } * ``` */ onError?: (_?: TError | null) => void; /** * Use a shared query client for micro-frontend scenarios where multiple app instances * need to share cache. * * Client types: * - `'page'`: Shared across all instances. Uses reference counting - disposes when last page client instance is disposed. * - `'app'`: Shared across all instances. Persists until browser refresh/close. * * @see {@link getQueryClient} for providing shared clients at the provider level (uses 'page' only) * @see {@link GlobalClientOptions} in client-helpers.ts for advanced configuration * @see TESTING.md — ContainerBuilder tests isolate from `window.queryClients` by default * * @example * ```typescript * // Use page-level shared client for this query * globalClient: 'page' * * // Use app-level shared client for this query * globalClient: 'app' * ``` */ globalClient?: GlobalClientOptions; /** * @deprecated Use `dedupe` option on `invalidate()` instead. Debounce will be removed in a future version. */ debounceInvalidateTime?: number; } /** * Core class that manages an individual TanStack Query and syncs its state to MobX observables. * * @template T - The type of data returned by the query * @template TError - The error type (default: AxiosError) * * @remarks * This class bridges TanStack Query's reactive system with MobX observables, * allowing query state to be seamlessly integrated into MobX stores. * * Key features: * - Observable state: `data`, `initialized`, `isLoading`, `isFetching`, `isError`, `error` * - Automatic refetch when `queryKey` dependencies change (via MobX reactions) * - Manual control: `invalidate()`, `updateQueryData()`, `cancel()`, `refetch()` * - Lifecycle management: automatic setup and cleanup * * Typically created via the `query()` factory with the `@queryStore` decorator, * or via `QueryApiStore.addQuery()` in the inheritance approach. * * @see {@link QueryApiOptions} for configuration options * @see `@queryStore` decorator (recommended) for automatic lifecycle management * @see {@link QueryApiStore} for the inheritance-based approach * * @example Recommended: `@queryStore` decorator with `query()` factory * ```typescript * @queryStore * class JobsStore extends Store { * @inject(JobsApi) private api?: JobsApi; * * jobs = query(() => ({ * queryKey: ['scheduling', 'jobs'], * queryFn: async () => (await this.api?.getJobs())?.data ?? [], * })); * * stats = query(() => ({ * queryKey: ['scheduling', 'stats'], * queryFn: async () => (await this.api?.getStats())?.data, * })); * } * ``` * * @example Inheritance: `QueryApiStore` with `addQuery()` * ```typescript * @injectable() * class JobsStore extends QueryApiStore { * @inject(JobsApi) private api?: JobsApi; * * get queryOptions(): QueryApiOptions { * return { * queryKey: ['scheduling', 'jobs'], * queryFn: async () => (await this.api?.getJobs())?.data ?? [], * }; * } * * stats = this.addQuery(() => ({ * queryKey: ['scheduling', 'stats'], * queryFn: async () => (await this.api?.getStats())?.data, * })); * } * ``` */ export declare class QueryApi implements IRefreshOnMountStore { /** * Becomes true after the first query attempt settles without any active fetch or invalidation. * Unlike TanStack Query's status flags, this is a package-specific readiness flag for store setup. */ initialized: boolean; /** * Mirrors TanStack Query's `isPending`. * True while the query has no settled result yet, including disabled queries that have never run. */ isPending: boolean; /** * Mirrors TanStack Query's `isLoading`. * True only while the first fetch is in flight (`isFetching && isPending`). */ isLoading: boolean; /** * Mirrors TanStack Query's `isFetching`. * True whenever the query function is executing, including the initial fetch and background refetches. */ isFetching: boolean; /** * Mirrors TanStack Query's `isRefetching`. * True during a background refetch after the query has already moved past the initial pending state. */ isRefetching: boolean; /** Mirrors TanStack Query's `isSuccess` derived status flag. */ isSuccess: boolean; /** Mirrors TanStack Query's `isError` derived status flag. */ isError: boolean; /** Mirrors TanStack Query's `error` value. Defaults to `null` when no error is present. */ error: TError | null; /** * Remaining TanStack Query observer result fields that are not exposed as top-level properties here. * This can include values such as `status`, `fetchStatus`, `failureCount`, and timestamps. */ queryInfo?: Partial>; /** * Mirrors TanStack Query's `refetch`. * Call this to manually rerun the query. */ refetch: QueryObserverResult['refetch']; storesToRefreshOnMount?: () => (IRefreshOnMountStore | undefined)[]; /** * The last query data snapshot exposed by this store. * Successful results are deep-cloned before assignment so consumers do not mutate cached data by accident. */ readonly data?: T; clientStore?: QueryClientStore; protected disposables: (() => void)[]; private observer?; private queryOptions; private overrideOptions; private invalidateDebounceFn; constructor(options?: () => QueryApiOptions); private get combinedOptions(); /** The current query key derived from options. */ get queryKey(): QueryKey | undefined; private get getQueryOptions(); /** * Connects this query to a QueryClientStore and starts observing TanStack Query state. * Call this during store initialization before reading reactive query state. */ setup(client?: QueryClientStore, overrides?: () => Partial>, refreshStores?: () => (IRefreshOnMountStore | undefined)[]): void; /** Cleans up reactions, query subscriptions, and any owned shared query client. */ dispose(): void; /** * Updates cached data for this query without running the query function. * This is equivalent to calling `queryClient.setQueryData` for the current query key. */ updateQueryData: (data: T) => void; /** Returns TanStack Query's cached query state for the current query key, if it exists. */ getQueryState: () => import("@tanstack/query-core").QueryState | undefined; /** * Invalidates the current query key so TanStack Query marks it stale and refetches as needed. * Use `dedupe: true` to skip invalidation if the query is already invalidated. * * Note: The `debounce` option is deprecated and will be removed in a future version. Use `dedupe` instead. */ invalidate: (options?: QueryInvalidationOptions) => void; /** Cancels any in-flight fetch for the current query key. */ cancel: () => void; /** Calls `refreshOnMount` on every dependent store returned by `storesToRefreshOnMount`. */ refreshStoresOnMount: () => void; /** * Refetches this query on mount when it has already initialized, is currently stale, * and `refetchOnMount` is enabled for the query. */ refreshOnMount: () => void; /** Returns true when TanStack Query currently considers this query stale. */ isStale: () => boolean; protected setupQuery: () => void; private setQueryState; private reactionOptions; } //# sourceMappingURL=query.api.d.ts.map