@effector-tanstack-query/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/dist/createBaseQuery.cjs +208 -0
- package/dist/createBaseQuery.cjs.map +1 -0
- package/dist/createBaseQuery.d.cts +114 -0
- package/dist/createBaseQuery.d.ts +114 -0
- package/dist/createBaseQuery.js +204 -0
- package/dist/createBaseQuery.js.map +1 -0
- package/dist/createInfiniteQuery.cjs +193 -0
- package/dist/createInfiniteQuery.cjs.map +1 -0
- package/dist/createInfiniteQuery.d.cts +8 -0
- package/dist/createInfiniteQuery.d.ts +8 -0
- package/dist/createInfiniteQuery.js +191 -0
- package/dist/createInfiniteQuery.js.map +1 -0
- package/dist/createInvalidate.cjs +37 -0
- package/dist/createInvalidate.cjs.map +1 -0
- package/dist/createInvalidate.d.cts +50 -0
- package/dist/createInvalidate.d.ts +50 -0
- package/dist/createInvalidate.js +35 -0
- package/dist/createInvalidate.js.map +1 -0
- package/dist/createMutation.cjs +177 -0
- package/dist/createMutation.cjs.map +1 -0
- package/dist/createMutation.d.cts +7 -0
- package/dist/createMutation.d.ts +7 -0
- package/dist/createMutation.js +175 -0
- package/dist/createMutation.js.map +1 -0
- package/dist/createQuery.cjs +98 -0
- package/dist/createQuery.cjs.map +1 -0
- package/dist/createQuery.d.cts +8 -0
- package/dist/createQuery.d.ts +8 -0
- package/dist/createQuery.js +96 -0
- package/dist/createQuery.js.map +1 -0
- package/dist/index.cjs +36 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/queryClient.cjs +20 -0
- package/dist/queryClient.cjs.map +1 -0
- package/dist/queryClient.d.cts +15 -0
- package/dist/queryClient.d.ts +15 -0
- package/dist/queryClient.js +17 -0
- package/dist/queryClient.js.map +1 -0
- package/dist/resolve.cjs +37 -0
- package/dist/resolve.cjs.map +1 -0
- package/dist/resolve.d.cts +17 -0
- package/dist/resolve.d.ts +17 -0
- package/dist/resolve.js +33 -0
- package/dist/resolve.js.map +1 -0
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +209 -0
- package/dist/types.d.ts +209 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
- package/src/createBaseQuery.ts +428 -0
- package/src/createInfiniteQuery.ts +291 -0
- package/src/createInvalidate.ts +104 -0
- package/src/createMutation.ts +271 -0
- package/src/createQuery.ts +155 -0
- package/src/index.ts +17 -0
- package/src/queryClient.ts +23 -0
- package/src/resolve.ts +50 -0
- package/src/types.ts +270 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { attach, createEvent, sample } from 'effector'
|
|
2
|
+
import { QueryObserver } from '@tanstack/query-core'
|
|
3
|
+
import type { QueryClient } from '@tanstack/query-core'
|
|
4
|
+
import { createBaseQuery, warnMissingName } from './createBaseQuery'
|
|
5
|
+
import { resolveReactiveRefetchInterval } from './resolve'
|
|
6
|
+
import type { CreateQueryOptions, QueryResult } from './types'
|
|
7
|
+
|
|
8
|
+
export function createQuery<
|
|
9
|
+
TQueryFnData = unknown,
|
|
10
|
+
TError = Error,
|
|
11
|
+
TData = TQueryFnData,
|
|
12
|
+
>(
|
|
13
|
+
options: CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
14
|
+
): QueryResult<TData, TError>
|
|
15
|
+
export function createQuery<
|
|
16
|
+
TQueryFnData = unknown,
|
|
17
|
+
TError = Error,
|
|
18
|
+
TData = TQueryFnData,
|
|
19
|
+
>(
|
|
20
|
+
queryClient: QueryClient,
|
|
21
|
+
options: CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
22
|
+
): QueryResult<TData, TError>
|
|
23
|
+
export function createQuery<
|
|
24
|
+
TQueryFnData = unknown,
|
|
25
|
+
TError = Error,
|
|
26
|
+
TData = TQueryFnData,
|
|
27
|
+
>(
|
|
28
|
+
arg1:
|
|
29
|
+
| QueryClient
|
|
30
|
+
| CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
31
|
+
arg2?: CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
32
|
+
): QueryResult<TData, TError> {
|
|
33
|
+
const [explicitClient, options] = parseQueryArgs<TQueryFnData, TError, TData>(
|
|
34
|
+
arg1,
|
|
35
|
+
arg2,
|
|
36
|
+
)
|
|
37
|
+
const { queryKey, enabled, name, ...restOptions } = options
|
|
38
|
+
|
|
39
|
+
if (!name) warnMissingName('createQuery')
|
|
40
|
+
|
|
41
|
+
// If `refetchInterval` is a Store, pull it out for reactive wiring in
|
|
42
|
+
// createBaseQuery — otherwise leave it in restOptions for the observer
|
|
43
|
+
// constructor (handles plain values and function forms unchanged).
|
|
44
|
+
const reactiveRefetchInterval = resolveReactiveRefetchInterval(
|
|
45
|
+
(restOptions as { refetchInterval?: unknown }).refetchInterval,
|
|
46
|
+
)
|
|
47
|
+
if (reactiveRefetchInterval) {
|
|
48
|
+
delete (restOptions as { refetchInterval?: unknown }).refetchInterval
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const base = createBaseQuery<
|
|
52
|
+
TData,
|
|
53
|
+
TError,
|
|
54
|
+
ReturnType<QueryObserver<TQueryFnData, TError, TData>['getCurrentResult']>,
|
|
55
|
+
QueryObserver<TQueryFnData, TError, TData>
|
|
56
|
+
>(
|
|
57
|
+
explicitClient,
|
|
58
|
+
{ queryKey, enabled, name, reactiveRefetchInterval },
|
|
59
|
+
{
|
|
60
|
+
createObserver: (qc, { queryKey: key, enabled: isEnabled }) =>
|
|
61
|
+
// Cast: restOptions's `refetchInterval` may still type as
|
|
62
|
+
// `Store | number | false | fn`; the Store form is deleted at runtime
|
|
63
|
+
// above, but TS can't narrow that here.
|
|
64
|
+
new QueryObserver<TQueryFnData, TError, TData>(qc, {
|
|
65
|
+
...restOptions,
|
|
66
|
+
queryKey: key,
|
|
67
|
+
enabled: isEnabled,
|
|
68
|
+
} as any),
|
|
69
|
+
},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Prefetch event: drives `queryClient.fetchQuery` directly (no Observer)
|
|
73
|
+
// and **awaits** the result, so `allSettled(query.prefetch, { scope })` on
|
|
74
|
+
// the server returns only after the cache has the data. Unlike `mounted`,
|
|
75
|
+
// which kicks off a background subscription and resolves immediately, this
|
|
76
|
+
// is the right primitive for SSR / route loaders. The current resolved key
|
|
77
|
+
// + enabled is read from the scope via attach — reactive keys work.
|
|
78
|
+
const prefetch = createEvent<void>()
|
|
79
|
+
const prefetchFx = attach({
|
|
80
|
+
source: {
|
|
81
|
+
qc: base.$queryClient,
|
|
82
|
+
key: base.$resolvedKey,
|
|
83
|
+
enabled: base.$enabled,
|
|
84
|
+
},
|
|
85
|
+
effect: ({ qc, key, enabled }) => {
|
|
86
|
+
if (!qc || !enabled) return
|
|
87
|
+
return qc.fetchQuery({
|
|
88
|
+
...restOptions,
|
|
89
|
+
queryKey: key,
|
|
90
|
+
} as any)
|
|
91
|
+
},
|
|
92
|
+
})
|
|
93
|
+
sample({ clock: prefetch, target: prefetchFx })
|
|
94
|
+
|
|
95
|
+
// Lazy `observer` field for backward compatibility — returns the
|
|
96
|
+
// default-scope observer (non-fork). Tests and advanced consumers that read
|
|
97
|
+
// `query.observer` after `query.mounted()` see the live observer. For
|
|
98
|
+
// fork-aware consumers, use `query.$observer` via `useUnit`.
|
|
99
|
+
const result: QueryResult<TData, TError> = {
|
|
100
|
+
$data: base.$data,
|
|
101
|
+
$error: base.$error,
|
|
102
|
+
$status: base.$status,
|
|
103
|
+
$isPending: base.$isPending,
|
|
104
|
+
$isFetching: base.$isFetching,
|
|
105
|
+
$isSuccess: base.$isSuccess,
|
|
106
|
+
$isError: base.$isError,
|
|
107
|
+
$isPlaceholderData: base.$isPlaceholderData,
|
|
108
|
+
$fetchStatus: base.$fetchStatus,
|
|
109
|
+
$observer: base.$observer as unknown as QueryResult<
|
|
110
|
+
TData,
|
|
111
|
+
TError
|
|
112
|
+
>['$observer'],
|
|
113
|
+
$queryClient: base.$queryClient,
|
|
114
|
+
refresh: base.refresh,
|
|
115
|
+
prefetch,
|
|
116
|
+
mounted: base.mounted,
|
|
117
|
+
unmounted: base.unmounted,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Internal: used by useSuspenseQuery to construct a transient observer
|
|
121
|
+
// when the suspense hook renders before mountFx has populated the scope's
|
|
122
|
+
// $observer (mountFx runs from useEffect, which is skipped while
|
|
123
|
+
// suspended). Not part of the public API; not in TS types.
|
|
124
|
+
Object.defineProperty(result, '__createObserver', {
|
|
125
|
+
enumerable: false,
|
|
126
|
+
value: (qc: QueryClient, init: { queryKey: any; enabled: boolean }) =>
|
|
127
|
+
new QueryObserver<TQueryFnData, TError, TData>(qc, {
|
|
128
|
+
...restOptions,
|
|
129
|
+
queryKey: init.queryKey,
|
|
130
|
+
enabled: init.enabled,
|
|
131
|
+
} as any),
|
|
132
|
+
})
|
|
133
|
+
Object.defineProperty(result, '__resolvedKey', {
|
|
134
|
+
enumerable: false,
|
|
135
|
+
value: base.$resolvedKey,
|
|
136
|
+
})
|
|
137
|
+
Object.defineProperty(result, '__enabled', {
|
|
138
|
+
enumerable: false,
|
|
139
|
+
value: base.$enabled,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
return result
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function parseQueryArgs<TQueryFnData, TError, TData>(
|
|
146
|
+
arg1:
|
|
147
|
+
| QueryClient
|
|
148
|
+
| CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
149
|
+
arg2?: CreateQueryOptions<TQueryFnData, TError, TData>,
|
|
150
|
+
): [QueryClient | null, CreateQueryOptions<TQueryFnData, TError, TData>] {
|
|
151
|
+
if (arg2 !== undefined) {
|
|
152
|
+
return [arg1 as QueryClient, arg2]
|
|
153
|
+
}
|
|
154
|
+
return [null, arg1 as CreateQueryOptions<TQueryFnData, TError, TData>]
|
|
155
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { createQuery } from './createQuery'
|
|
2
|
+
export { createInfiniteQuery } from './createInfiniteQuery'
|
|
3
|
+
export { createMutation } from './createMutation'
|
|
4
|
+
export { createInvalidate } from './createInvalidate'
|
|
5
|
+
export type { CreateInvalidateOptions } from './createInvalidate'
|
|
6
|
+
export { $queryClient, setQueryClient } from './queryClient'
|
|
7
|
+
export type {
|
|
8
|
+
CreateInfiniteQueryOptions,
|
|
9
|
+
CreateMutationOptions,
|
|
10
|
+
CreateQueryOptions,
|
|
11
|
+
EffectorQueryKey,
|
|
12
|
+
InfiniteQueryResult,
|
|
13
|
+
MutationResult,
|
|
14
|
+
MutationStatus,
|
|
15
|
+
QueryResult,
|
|
16
|
+
StoreOrValue,
|
|
17
|
+
} from './types'
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createEvent, createStore } from 'effector'
|
|
2
|
+
import type { QueryClient } from '@tanstack/query-core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Holds the default `QueryClient` used when a factory (`createQuery`,
|
|
6
|
+
* `createInfiniteQuery`, `createMutation`) is called without an explicit one.
|
|
7
|
+
*
|
|
8
|
+
* Per-scope isolation: under `fork({ values: [[$queryClient, qc]] })`, every
|
|
9
|
+
* factory in that scope uses its own client. Observers are created lazily on
|
|
10
|
+
* mount, reading this store via `attach`, so each scope gets its own observer.
|
|
11
|
+
*/
|
|
12
|
+
export const $queryClient = createStore<QueryClient | null>(null, {
|
|
13
|
+
name: '@tanstack/query-effector.$queryClient',
|
|
14
|
+
sid: '@tanstack/query-effector.$queryClient',
|
|
15
|
+
// Carries a runtime-only object (`QueryClient` instance) — must not
|
|
16
|
+
// round-trip through `serialize(scope)`. Per-scope injection happens
|
|
17
|
+
// via `fork({ values: [[$queryClient, qc]] })` instead.
|
|
18
|
+
serialize: 'ignore',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const setQueryClient = createEvent<QueryClient>()
|
|
22
|
+
|
|
23
|
+
$queryClient.on(setQueryClient, (_, qc) => qc)
|
package/src/resolve.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { combine, createStore, is } from 'effector'
|
|
2
|
+
import type { Store } from 'effector'
|
|
3
|
+
import type { QueryKey } from '@tanstack/query-core'
|
|
4
|
+
import type { EffectorQueryKey, StoreOrValue } from './types'
|
|
5
|
+
|
|
6
|
+
export function resolveKey(key: EffectorQueryKey): Store<QueryKey> {
|
|
7
|
+
const storePositions: Array<number> = []
|
|
8
|
+
const stores: Array<Store<unknown>> = []
|
|
9
|
+
|
|
10
|
+
key.forEach((item, i) => {
|
|
11
|
+
if (is.store(item)) {
|
|
12
|
+
storePositions.push(i)
|
|
13
|
+
stores.push(item as Store<unknown>)
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
if (stores.length === 0) {
|
|
18
|
+
return createStore(key as QueryKey)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return combine(stores).map((values) =>
|
|
22
|
+
key.map((item, i) => {
|
|
23
|
+
const storeIdx = storePositions.indexOf(i)
|
|
24
|
+
return storeIdx >= 0 ? values[storeIdx] : item
|
|
25
|
+
}),
|
|
26
|
+
) as Store<QueryKey>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function resolveEnabled(
|
|
30
|
+
enabled: StoreOrValue<boolean> | undefined,
|
|
31
|
+
): Store<boolean> {
|
|
32
|
+
if (is.store(enabled)) return enabled
|
|
33
|
+
return createStore(enabled ?? true)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `refetchInterval` accepts a static value, a function `(query) => …`, or an
|
|
38
|
+
* effector `Store<number | false>`. Only the Store form is "reactive" — the
|
|
39
|
+
* function form is evaluated by the observer on every tick and stays in the
|
|
40
|
+
* observer's options. Returns the store if one was passed, `undefined`
|
|
41
|
+
* otherwise (signaling the per-flavor factory to keep the value in
|
|
42
|
+
* `restOptions` for the observer constructor).
|
|
43
|
+
*/
|
|
44
|
+
export function resolveReactiveRefetchInterval(
|
|
45
|
+
value: unknown,
|
|
46
|
+
): Store<number | false | undefined> | undefined {
|
|
47
|
+
return is.store(value)
|
|
48
|
+
? (value as Store<number | false | undefined>)
|
|
49
|
+
: undefined
|
|
50
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { Event, EventCallable, Store } from 'effector'
|
|
2
|
+
import type {
|
|
3
|
+
FetchStatus,
|
|
4
|
+
InfiniteData,
|
|
5
|
+
InfiniteQueryObserver,
|
|
6
|
+
InfiniteQueryObserverOptions,
|
|
7
|
+
MutateOptions,
|
|
8
|
+
MutationObserver,
|
|
9
|
+
MutationObserverOptions,
|
|
10
|
+
QueryClient,
|
|
11
|
+
QueryKey,
|
|
12
|
+
QueryObserver,
|
|
13
|
+
QueryObserverOptions,
|
|
14
|
+
QueryStatus,
|
|
15
|
+
} from '@tanstack/query-core'
|
|
16
|
+
|
|
17
|
+
export type StoreOrValue<T> = Store<T> | T
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A query key where each element can be a plain value or an effector Store.
|
|
21
|
+
* When any Store changes, the query is automatically re-executed with the new key.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const $userId = createStore(1)
|
|
25
|
+
* queryKey: ['user', $userId, 'details']
|
|
26
|
+
*/
|
|
27
|
+
export type EffectorQueryKey = ReadonlyArray<
|
|
28
|
+
StoreOrValue<string | number | bigint | boolean | null | undefined | object>
|
|
29
|
+
>
|
|
30
|
+
|
|
31
|
+
export interface CreateQueryOptions<
|
|
32
|
+
TQueryFnData = unknown,
|
|
33
|
+
TError = Error,
|
|
34
|
+
TData = TQueryFnData,
|
|
35
|
+
> extends Omit<
|
|
36
|
+
QueryObserverOptions<TQueryFnData, TError, TData>,
|
|
37
|
+
'queryKey' | 'enabled' | 'refetchInterval'
|
|
38
|
+
> {
|
|
39
|
+
queryKey: EffectorQueryKey
|
|
40
|
+
enabled?: StoreOrValue<boolean>
|
|
41
|
+
/**
|
|
42
|
+
* Polling interval in milliseconds, `false` to disable, or a Store for
|
|
43
|
+
* runtime toggling — `Store<number | false>`. When a Store is passed, the
|
|
44
|
+
* observer's `refetchInterval` is automatically kept in sync via
|
|
45
|
+
* `setOptions` on every store change. The function form (`(query) => …`)
|
|
46
|
+
* from TanStack Query is also still supported.
|
|
47
|
+
*/
|
|
48
|
+
refetchInterval?:
|
|
49
|
+
| QueryObserverOptions<TQueryFnData, TError, TData>['refetchInterval']
|
|
50
|
+
| Store<number | false | undefined>
|
|
51
|
+
/**
|
|
52
|
+
* Stable name used to derive SIDs for the internal effector stores so that
|
|
53
|
+
* `serialize(scope)` / `fork({ values })` round-trip works for SSR. Without
|
|
54
|
+
* a name, the queryClient's `dehydrate`/`hydrate` path still works, but
|
|
55
|
+
* scope-only serialization will silently drop these stores.
|
|
56
|
+
*/
|
|
57
|
+
name?: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface QueryResult<TData, TError = Error> {
|
|
61
|
+
/** The resolved query data, or `undefined` while loading */
|
|
62
|
+
$data: Store<TData | undefined>
|
|
63
|
+
/** The query error, or `null` if there is none */
|
|
64
|
+
$error: Store<TError | null>
|
|
65
|
+
/** The query status: `'pending'` | `'success'` | `'error'` */
|
|
66
|
+
$status: Store<QueryStatus>
|
|
67
|
+
/** `true` while there is no cached data and the query is fetching */
|
|
68
|
+
$isPending: Store<boolean>
|
|
69
|
+
/** `true` while the query is fetching in the background */
|
|
70
|
+
$isFetching: Store<boolean>
|
|
71
|
+
/** `true` when the query has successfully fetched data */
|
|
72
|
+
$isSuccess: Store<boolean>
|
|
73
|
+
/** `true` when the query has failed */
|
|
74
|
+
$isError: Store<boolean>
|
|
75
|
+
/** `true` when the displayed data is placeholder data (not yet fetched for current key) */
|
|
76
|
+
$isPlaceholderData: Store<boolean>
|
|
77
|
+
/** The fetch status: `'fetching'` | `'paused'` | `'idle'` */
|
|
78
|
+
$fetchStatus: Store<FetchStatus>
|
|
79
|
+
/** Invalidates the query and triggers a background refetch */
|
|
80
|
+
refresh: EventCallable<void>
|
|
81
|
+
/**
|
|
82
|
+
* Fetches the query via `queryClient.fetchQuery` and **awaits** the result.
|
|
83
|
+
* Unlike `mounted`, this is meant for server-side prefetching / route
|
|
84
|
+
* loaders where you need the cache populated before responding to the
|
|
85
|
+
* request — `await allSettled(query.prefetch, { scope })` returns only
|
|
86
|
+
* after the queryFn has resolved. Skips automatically when `enabled` is
|
|
87
|
+
* `false`.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* await allSettled(query.prefetch, { scope })
|
|
91
|
+
* // queryClient cache + scope are now ready to be dehydrated/serialized.
|
|
92
|
+
*/
|
|
93
|
+
prefetch: EventCallable<void>
|
|
94
|
+
/**
|
|
95
|
+
* Initializes the query subscription. Must be called (or used with allSettled)
|
|
96
|
+
* before the query starts fetching.
|
|
97
|
+
*
|
|
98
|
+
* @example Without fork
|
|
99
|
+
* query.mounted()
|
|
100
|
+
*
|
|
101
|
+
* @example With fork (test isolation)
|
|
102
|
+
* const scope = fork()
|
|
103
|
+
* await allSettled(query.mounted, { scope })
|
|
104
|
+
*/
|
|
105
|
+
mounted: EventCallable<void>
|
|
106
|
+
/**
|
|
107
|
+
* Tears down the query subscription and cancels any in-flight request.
|
|
108
|
+
* Call this when the consumer is destroyed (e.g. component unmount).
|
|
109
|
+
*/
|
|
110
|
+
unmounted: EventCallable<void>
|
|
111
|
+
/**
|
|
112
|
+
* Per-scope observer store. Each fork scope has its own Observer instance,
|
|
113
|
+
* created lazily on `mounted()` and bound to that scope's QueryClient.
|
|
114
|
+
* Read scope-aware via `useUnit($observer)`. For tests, prefer
|
|
115
|
+
* `scope.getState($observer)` over reading the default scope state.
|
|
116
|
+
*/
|
|
117
|
+
$observer: Store<QueryObserver<TData, TError> | null>
|
|
118
|
+
/**
|
|
119
|
+
* The QueryClient store this query is bound to. Frozen if a client was
|
|
120
|
+
* passed explicitly to the factory; otherwise points at the global
|
|
121
|
+
* `$queryClient` and honors `fork({ values: [[$queryClient, qc]] })`.
|
|
122
|
+
*/
|
|
123
|
+
$queryClient: Store<QueryClient | null>
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface CreateInfiniteQueryOptions<
|
|
127
|
+
TQueryFnData = unknown,
|
|
128
|
+
TError = Error,
|
|
129
|
+
TPageParam = unknown,
|
|
130
|
+
TData = InfiniteData<TQueryFnData, TPageParam>,
|
|
131
|
+
> extends Omit<
|
|
132
|
+
InfiniteQueryObserverOptions<
|
|
133
|
+
TQueryFnData,
|
|
134
|
+
TError,
|
|
135
|
+
TData,
|
|
136
|
+
ReadonlyArray<unknown>,
|
|
137
|
+
TPageParam
|
|
138
|
+
>,
|
|
139
|
+
'queryKey' | 'enabled' | 'refetchInterval'
|
|
140
|
+
> {
|
|
141
|
+
queryKey: EffectorQueryKey
|
|
142
|
+
enabled?: StoreOrValue<boolean>
|
|
143
|
+
/** See {@link CreateQueryOptions.refetchInterval}. */
|
|
144
|
+
refetchInterval?:
|
|
145
|
+
| InfiniteQueryObserverOptions<
|
|
146
|
+
TQueryFnData,
|
|
147
|
+
TError,
|
|
148
|
+
TData,
|
|
149
|
+
ReadonlyArray<unknown>,
|
|
150
|
+
TPageParam
|
|
151
|
+
>['refetchInterval']
|
|
152
|
+
| Store<number | false | undefined>
|
|
153
|
+
/** See {@link CreateQueryOptions.name}. */
|
|
154
|
+
name?: string
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface InfiniteQueryResult<
|
|
158
|
+
TData,
|
|
159
|
+
TError = Error,
|
|
160
|
+
TPageParam = unknown,
|
|
161
|
+
> {
|
|
162
|
+
/**
|
|
163
|
+
* The selected/displayed data. Defaults to `InfiniteData<TQueryFnData, TPageParam>`
|
|
164
|
+
* but narrows to whatever `select` returns when provided.
|
|
165
|
+
*/
|
|
166
|
+
$data: Store<TData | undefined>
|
|
167
|
+
$error: Store<TError | null>
|
|
168
|
+
$status: Store<QueryStatus>
|
|
169
|
+
$isPending: Store<boolean>
|
|
170
|
+
$isFetching: Store<boolean>
|
|
171
|
+
$isSuccess: Store<boolean>
|
|
172
|
+
$isError: Store<boolean>
|
|
173
|
+
$isPlaceholderData: Store<boolean>
|
|
174
|
+
$fetchStatus: Store<FetchStatus>
|
|
175
|
+
$hasNextPage: Store<boolean>
|
|
176
|
+
$hasPreviousPage: Store<boolean>
|
|
177
|
+
$isFetchingNextPage: Store<boolean>
|
|
178
|
+
$isFetchingPreviousPage: Store<boolean>
|
|
179
|
+
$isFetchNextPageError: Store<boolean>
|
|
180
|
+
$isFetchPreviousPageError: Store<boolean>
|
|
181
|
+
fetchNextPage: EventCallable<void>
|
|
182
|
+
fetchPreviousPage: EventCallable<void>
|
|
183
|
+
refresh: EventCallable<void>
|
|
184
|
+
/** See {@link QueryResult.prefetch}. Uses `fetchInfiniteQuery` under the hood. */
|
|
185
|
+
prefetch: EventCallable<void>
|
|
186
|
+
mounted: EventCallable<void>
|
|
187
|
+
unmounted: EventCallable<void>
|
|
188
|
+
/** See {@link QueryResult.$observer}. */
|
|
189
|
+
$observer: Store<
|
|
190
|
+
InfiniteQueryObserver<any, TError, TData, QueryKey, TPageParam> | null
|
|
191
|
+
>
|
|
192
|
+
/** See {@link QueryResult.$queryClient}. */
|
|
193
|
+
$queryClient: Store<QueryClient | null>
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export type CreateMutationOptions<
|
|
197
|
+
TData = unknown,
|
|
198
|
+
TError = Error,
|
|
199
|
+
TVariables = void,
|
|
200
|
+
TOnMutateResult = unknown,
|
|
201
|
+
> = MutationObserverOptions<TData, TError, TVariables, TOnMutateResult> & {
|
|
202
|
+
/** See {@link CreateQueryOptions.name}. */
|
|
203
|
+
name?: string
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export type MutationStatus = 'idle' | 'pending' | 'success' | 'error'
|
|
207
|
+
|
|
208
|
+
export interface MutationResult<
|
|
209
|
+
TData = unknown,
|
|
210
|
+
TError = Error,
|
|
211
|
+
TVariables = void,
|
|
212
|
+
> {
|
|
213
|
+
/** The mutation result data, or `undefined` before success */
|
|
214
|
+
$data: Store<TData | undefined>
|
|
215
|
+
/** The mutation error, or `null` if there is none */
|
|
216
|
+
$error: Store<TError | null>
|
|
217
|
+
/** The mutation status: `'idle'` | `'pending'` | `'success'` | `'error'` */
|
|
218
|
+
$status: Store<MutationStatus>
|
|
219
|
+
/** The variables passed to the last `mutate` call */
|
|
220
|
+
$variables: Store<TVariables | undefined>
|
|
221
|
+
/** `true` while the mutation is paused (e.g. offline) and cannot run */
|
|
222
|
+
$isPaused: Store<boolean>
|
|
223
|
+
/** `true` while the mutation is executing */
|
|
224
|
+
$isPending: Store<boolean>
|
|
225
|
+
/** `true` when the mutation has succeeded */
|
|
226
|
+
$isSuccess: Store<boolean>
|
|
227
|
+
/** `true` when the mutation has failed */
|
|
228
|
+
$isError: Store<boolean>
|
|
229
|
+
/** `true` when the mutation has not yet been triggered */
|
|
230
|
+
$isIdle: Store<boolean>
|
|
231
|
+
/** Per-scope MutationObserver. Created on `start()`. See {@link QueryResult.$observer}. */
|
|
232
|
+
$observer: Store<MutationObserver<TData, TError, TVariables, any> | null>
|
|
233
|
+
/** See {@link QueryResult.$queryClient}. */
|
|
234
|
+
$queryClient: Store<QueryClient | null>
|
|
235
|
+
/** Triggers the mutation with the given variables */
|
|
236
|
+
mutate: EventCallable<TVariables>
|
|
237
|
+
/**
|
|
238
|
+
* Triggers the mutation with per-call callbacks layered on top of the
|
|
239
|
+
* observer-level ones. Use when you need component-local reactions
|
|
240
|
+
* (e.g. navigate after success) without module-level `sample` wiring.
|
|
241
|
+
*/
|
|
242
|
+
mutateWith: EventCallable<{
|
|
243
|
+
variables: TVariables
|
|
244
|
+
onSuccess?: MutateOptions<TData, TError, TVariables>['onSuccess']
|
|
245
|
+
onError?: MutateOptions<TData, TError, TVariables>['onError']
|
|
246
|
+
onSettled?: MutateOptions<TData, TError, TVariables>['onSettled']
|
|
247
|
+
}>
|
|
248
|
+
/** Resets the mutation state back to idle */
|
|
249
|
+
reset: EventCallable<void>
|
|
250
|
+
/**
|
|
251
|
+
* Initializes the mutation observer subscription.
|
|
252
|
+
* Must be called before mutate to ensure stores receive updates.
|
|
253
|
+
*/
|
|
254
|
+
start: EventCallable<void>
|
|
255
|
+
/**
|
|
256
|
+
* Tears down the observer subscription. Call this when the consumer is
|
|
257
|
+
* destroyed (e.g. component unmount) so the queryClient can gc the
|
|
258
|
+
* mutation entry.
|
|
259
|
+
*/
|
|
260
|
+
unmounted: EventCallable<void>
|
|
261
|
+
/**
|
|
262
|
+
* Sample-friendly events for module-level reactions to mutation outcome.
|
|
263
|
+
* Payloads include both the original `params` and the `result` / `error`,
|
|
264
|
+
* matching effector effect `done` / `fail` shape.
|
|
265
|
+
*/
|
|
266
|
+
finished: {
|
|
267
|
+
success: Event<{ params: TVariables; result: TData }>
|
|
268
|
+
failure: Event<{ params: TVariables; error: TError }>
|
|
269
|
+
}
|
|
270
|
+
}
|