@raf-query/core 0.11.0 → 0.12.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/CHANGELOG.md +18 -2
- package/README.md +28 -18
- package/dist/client.d.mts +132 -119
- package/dist/client.mjs +59 -162
- package/dist/entry.d.mts +67 -148
- package/dist/entry.mjs +303 -474
- package/dist/features/focus-refetch/focus-refetch.d.mts +15 -0
- package/dist/features/focus-refetch/focus-refetch.mjs +18 -0
- package/dist/features/polling/polling.d.mts +12 -0
- package/dist/features/polling/polling.mjs +35 -0
- package/dist/features/reconnect-refetch/reconnect-refetch.d.mts +15 -0
- package/dist/features/reconnect-refetch/reconnect-refetch.mjs +14 -0
- package/dist/features/shared.mjs +13 -0
- package/dist/guards.mjs +23 -0
- package/dist/hydration/hydration.d.mts +73 -0
- package/dist/hydration/hydration.mjs +128 -0
- package/dist/index.d.mts +18 -13
- package/dist/index.mjs +15 -13
- package/dist/infinite/infinite.d.mts +71 -0
- package/dist/infinite/infinite.mjs +88 -0
- package/dist/internal.d.mts +13 -0
- package/dist/internal.mjs +7 -0
- package/dist/keys/keys.d.mts +46 -0
- package/dist/keys/keys.mjs +53 -0
- package/dist/keys/targets.d.mts +56 -0
- package/dist/keys/targets.mjs +85 -0
- package/dist/links/retry/retry.d.mts +26 -0
- package/dist/links/retry/retry.mjs +51 -0
- package/dist/links/timeout/timeout.d.mts +9 -0
- package/dist/links/timeout/timeout.mjs +27 -0
- package/dist/load.d.mts +124 -0
- package/dist/load.mjs +165 -0
- package/dist/options.d.mts +112 -338
- package/dist/options.mjs +25 -36
- package/dist/presets.d.mts +29 -0
- package/dist/presets.mjs +25 -0
- package/dist/root.d.mts +82 -0
- package/dist/structural-sharing/structural-sharing.mjs +32 -0
- package/dist/subscribe.d.mts +15 -0
- package/dist/subscribe.mjs +29 -0
- package/dist/thenable.d.mts +13 -17
- package/dist/thenable.mjs +25 -6
- package/dist/verbs.d.mts +109 -0
- package/dist/verbs.mjs +87 -0
- package/package.json +13 -9
- package/dist/_virtual/_rolldown/runtime.mjs +0 -13
- package/dist/all-keyed.d.mts +0 -18
- package/dist/all-keyed.mjs +0 -19
- package/dist/binding.d.mts +0 -92
- package/dist/binding.mjs +0 -186
- package/dist/cache.d.mts +0 -164
- package/dist/cache.mjs +0 -184
- package/dist/controls.d.mts +0 -93
- package/dist/controls.mjs +0 -69
- package/dist/hydration.d.mts +0 -84
- package/dist/hydration.mjs +0 -148
- package/dist/infinite.d.mts +0 -5
- package/dist/infinite.mjs +0 -103
- package/dist/key.d.mts +0 -18
- package/dist/key.mjs +0 -36
- package/dist/listen.mjs +0 -19
- package/dist/notify.mjs +0 -21
- package/dist/observer.d.mts +0 -110
- package/dist/observer.mjs +0 -300
- package/dist/platform.d.mts +0 -27
- package/dist/platform.mjs +0 -44
- package/dist/query.d.mts +0 -137
- package/dist/query.mjs +0 -147
- package/dist/request.mjs +0 -47
- package/dist/retry.mjs +0 -25
- package/dist/share.mjs +0 -40
package/dist/options.d.mts
CHANGED
|
@@ -1,361 +1,135 @@
|
|
|
1
|
-
import { QueryKey } from "./
|
|
2
|
-
import {
|
|
1
|
+
import { QueryKey } from "./keys/keys.mjs";
|
|
2
|
+
import { AnyRoot, DefaultTypes, RootOf, RootTag, RootTypes } from "./root.mjs";
|
|
3
3
|
//#region src/options.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* {@link QueryKey}.
|
|
10
|
-
*
|
|
11
|
-
* ```ts
|
|
12
|
-
* type PostOptions = QueryOptions<{ data: Post }>;
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export interface QueryTypes {
|
|
16
|
-
readonly data: unknown;
|
|
17
|
-
readonly error?: unknown;
|
|
18
|
-
readonly key?: QueryKey;
|
|
19
|
-
readonly services?: unknown;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* The types of a paged query: one page, the param that loads it, and as in
|
|
23
|
-
* {@link QueryTypes}, an Effect `queryFn`'s error and services and the key.
|
|
24
|
-
*/
|
|
25
|
-
export interface InfiniteQueryTypes {
|
|
26
|
-
readonly error?: unknown;
|
|
27
|
-
readonly key?: QueryKey;
|
|
28
|
-
readonly page: unknown;
|
|
29
|
-
readonly pageParam: unknown;
|
|
30
|
-
readonly services?: unknown;
|
|
31
|
-
}
|
|
32
|
-
/** `error` of a types bag, `unknown` when it has none. */
|
|
33
|
-
type ErrorIn<TTypes> = TTypes extends {
|
|
34
|
-
readonly error: infer TError;
|
|
35
|
-
} ? TError : unknown;
|
|
36
|
-
/** `services` of a types bag, `never` when it has none. */
|
|
37
|
-
type ServicesIn<TTypes> = TTypes extends {
|
|
38
|
-
readonly services: infer TServices;
|
|
39
|
-
} ? TServices : never;
|
|
40
|
-
/** `key` of a types bag, any {@link QueryKey} when it has none. */
|
|
41
|
-
type KeyIn<TTypes> = TTypes extends {
|
|
42
|
-
readonly key: infer TKey extends QueryKey;
|
|
43
|
-
} ? TKey : QueryKey;
|
|
44
|
-
/**
|
|
45
|
-
* The bag `queryOptions` returns. `error` is left out when the `queryFn`
|
|
46
|
-
* doesn't name one (`unknown`: a promise or a plain value). `services` is
|
|
47
|
-
* left out when the `queryFn` needs none (`never`). An Effect's error,
|
|
48
|
-
* including `never` when it can't fail, stays. `key` is always there, so two
|
|
49
|
-
* factories with different key shapes have different types.
|
|
50
|
-
*/
|
|
51
|
-
type QueryTypesOf<TData, TError, TServices, TKey> = unknown extends TError ? [TServices] extends [never] ? {
|
|
52
|
-
data: TData;
|
|
53
|
-
key: TKey;
|
|
54
|
-
} : {
|
|
55
|
-
data: TData;
|
|
56
|
-
key: TKey;
|
|
57
|
-
services: TServices;
|
|
58
|
-
} : [TServices] extends [never] ? {
|
|
59
|
-
data: TData;
|
|
60
|
-
error: TError;
|
|
61
|
-
key: TKey;
|
|
62
|
-
} : {
|
|
63
|
-
data: TData;
|
|
64
|
-
error: TError;
|
|
65
|
-
key: TKey;
|
|
66
|
-
services: TServices;
|
|
67
|
-
};
|
|
68
|
-
/** As {@link QueryTypesOf}, for a paged query. */
|
|
69
|
-
type InfiniteQueryTypesOf<TPage, TPageParam, TError, TServices, TKey> = unknown extends TError ? [TServices] extends [never] ? {
|
|
70
|
-
key: TKey;
|
|
71
|
-
page: TPage;
|
|
72
|
-
pageParam: TPageParam;
|
|
73
|
-
} : {
|
|
74
|
-
key: TKey;
|
|
75
|
-
page: TPage;
|
|
76
|
-
pageParam: TPageParam;
|
|
77
|
-
services: TServices;
|
|
78
|
-
} : [TServices] extends [never] ? {
|
|
79
|
-
error: TError;
|
|
80
|
-
key: TKey;
|
|
81
|
-
page: TPage;
|
|
82
|
-
pageParam: TPageParam;
|
|
83
|
-
} : {
|
|
84
|
-
error: TError;
|
|
85
|
-
key: TKey;
|
|
86
|
-
page: TPage;
|
|
87
|
-
pageParam: TPageParam;
|
|
88
|
-
services: TServices;
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* What a `queryFn` may return: a value, a promise, or an `Effect`. An
|
|
92
|
-
* Effect's error type becomes the query's (promises reject with `unknown`),
|
|
93
|
-
* and the services it needs become requirements of the verbs that start it.
|
|
94
|
-
*/
|
|
95
|
-
export type QueryFnResult<TTypes extends QueryTypes> = TTypes["data"] | PromiseLike<TTypes["data"]> | Effect.Effect<TTypes["data"], ErrorIn<TTypes>, ServicesIn<TTypes>>;
|
|
96
|
-
/**
|
|
97
|
-
* App-wide types, filled in by module augmentation. Declare `queryMeta` to
|
|
98
|
-
* type every query's `meta`. Augment the package you import from;
|
|
99
|
-
* `@raf-query/react` re-exports this interface, so either works:
|
|
100
|
-
*
|
|
101
|
-
* ```ts
|
|
102
|
-
* declare module "@raf-query/react" {
|
|
103
|
-
* interface Register {
|
|
104
|
-
* queryMeta: { errorMessage?: string };
|
|
105
|
-
* }
|
|
106
|
-
* }
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
export interface Register {}
|
|
110
|
-
/**
|
|
111
|
-
* Type of a query's `meta`. `Record<string, unknown>` unless `queryMeta` is
|
|
112
|
-
* declared on {@link Register}.
|
|
113
|
-
*/
|
|
114
|
-
export type QueryMeta = Register extends {
|
|
115
|
-
queryMeta: infer TQueryMeta;
|
|
116
|
-
} ? TQueryMeta : Record<string, unknown>;
|
|
117
|
-
export interface QueryFunctionContext {
|
|
118
|
-
/** The query's `meta` when this request started ({@link QueryBehavior.meta}). */
|
|
119
|
-
readonly meta: QueryMeta | undefined;
|
|
120
|
-
/** The query's key, as returned by the factory. */
|
|
121
|
-
readonly queryKey: QueryKey;
|
|
122
|
-
/** Aborted when the request is cancelled or superseded. */
|
|
4
|
+
export interface QueryFunctionContext<TKey extends QueryKey = QueryKey> {
|
|
5
|
+
/** The query's `meta`, typed by its root where the query is defined. */
|
|
6
|
+
readonly meta: object;
|
|
7
|
+
readonly queryKey: TKey;
|
|
8
|
+
/** Aborted when the request is restarted or its entry is removed. */
|
|
123
9
|
readonly signal: AbortSignal;
|
|
124
10
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* How many times to retry a failed request: `false`, `true` (forever), a
|
|
132
|
-
* count, a predicate, or an Effect `Schedule`. The predicate gets the number
|
|
133
|
-
* of failures so far (1 after the first).
|
|
134
|
-
*/
|
|
135
|
-
export type RetryPolicy = boolean | number | Schedule.Schedule<unknown, unknown> | ((failureCount: number, error: unknown) => boolean);
|
|
136
|
-
/** Options every query accepts. `QueryCache` defaults fill in the rest. */
|
|
137
|
-
export interface QueryBehavior {
|
|
138
|
-
/**
|
|
139
|
-
* `false` keeps the query from running. Default `true`. The factory
|
|
140
|
-
* decides per call, so `enabled: typeof window !== "undefined"` runs a
|
|
141
|
-
* query only in the browser, for data only a browser has (permissions,
|
|
142
|
-
* device APIs, `localStorage`).
|
|
143
|
-
*
|
|
144
|
-
* While disabled, readers see `isPending`, `ensure` and `fetch` fail with
|
|
145
|
-
* `Query.DisabledError`, and `invalidate`, `reset` and `refetch` do
|
|
146
|
-
* nothing. In the browser, its promise stays pending until a factory
|
|
147
|
-
* call returns `true` and runs it. A server cache never sends it, and its
|
|
148
|
-
* promise rejects with `Query.DisabledError`: under Suspense, React
|
|
149
|
-
* renders the fallback on the server and the component in the browser.
|
|
150
|
-
*/
|
|
151
|
-
readonly enabled?: boolean;
|
|
152
|
-
/** How long an unread entry stays cached, in ms. `Infinity` keeps it. */
|
|
11
|
+
declare const dataTag: unique symbol;
|
|
12
|
+
/** Options every query takes. */
|
|
13
|
+
export interface BaseOptions<TKey extends QueryKey, TTypes extends RootTypes = RootTypes> {
|
|
14
|
+
/** How long an entry with no reader stays cached. Default 5 minutes; never on the server. */
|
|
153
15
|
readonly gcTime?: number;
|
|
154
16
|
/**
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
17
|
+
* Settings for the root's links and features, and data for targets: the
|
|
18
|
+
* fields the root's parts declare, such as `retry` with the `retry()`
|
|
19
|
+
* link.
|
|
158
20
|
*/
|
|
159
|
-
readonly meta?:
|
|
160
|
-
/**
|
|
161
|
-
readonly
|
|
162
|
-
/**
|
|
163
|
-
readonly refetchOnWindowFocus?: boolean;
|
|
164
|
-
/** Retries after a failed request. */
|
|
165
|
-
readonly retry?: RetryPolicy;
|
|
166
|
-
/** Delay before retry number `failureCount` (1-based), in ms. */
|
|
167
|
-
readonly retryDelay?: number | ((failureCount: number, error: unknown) => number);
|
|
168
|
-
/** How long data counts as fresh, in ms. Fresh data is never refetched. */
|
|
21
|
+
readonly meta?: NoInfer<Partial<TTypes["meta"]>>;
|
|
22
|
+
/** A plain array, usually built by a `group()`. Handles keep its literal type. */
|
|
23
|
+
readonly queryKey: TKey;
|
|
24
|
+
/** How long data stays fresh, in ms. Default `0`. */
|
|
169
25
|
readonly staleTime?: number;
|
|
170
|
-
/**
|
|
171
|
-
* Keep the parts of new data that are deeply equal to the old data, so
|
|
172
|
-
* unchanged objects keep their identity and unchanged data keeps its
|
|
173
|
-
* promise. Compares plain objects and arrays. Default `true`.
|
|
174
|
-
*/
|
|
26
|
+
/** Keep the deeply equal parts of new data, so they keep their identity. Default `true`. */
|
|
175
27
|
readonly structuralSharing?: boolean;
|
|
176
28
|
}
|
|
177
|
-
|
|
178
|
-
interface
|
|
179
|
-
/**
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
readonly
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
/** Keep at most this many pages; the far end is dropped when paging. */
|
|
212
|
-
readonly maxPages?: number;
|
|
213
|
-
readonly queryKey: KeyIn<TTypes>;
|
|
214
|
-
}
|
|
215
|
-
/** Data of a paged query. */
|
|
216
|
-
export interface InfiniteData<TTypes extends Pick<InfiniteQueryTypes, "page" | "pageParam">> {
|
|
217
|
-
readonly pageParams: ReadonlyArray<TTypes["pageParam"]>;
|
|
218
|
-
readonly pages: ReadonlyArray<TTypes["page"]>;
|
|
29
|
+
/** What `queryOptions` and `infiniteQueryOptions` return. */
|
|
30
|
+
export interface QueryOptions<TKey extends QueryKey = QueryKey, TQueryFnData = unknown, TData = TQueryFnData, TTypes extends RootTypes = RootTypes> extends BaseOptions<TKey, TTypes> {
|
|
31
|
+
/** Phantom: the root the builder is bound to. Never set at runtime. */
|
|
32
|
+
readonly "~root"?: RootTag<TTypes>;
|
|
33
|
+
/** Set by `infiniteQueryOptions`: runs the request page by page. */
|
|
34
|
+
readonly "~run"?: (op: never) => Promise<unknown>;
|
|
35
|
+
readonly [dataTag]?: TData;
|
|
36
|
+
readonly queryFn: (context: never) => unknown;
|
|
37
|
+
readonly select?: (data: TQueryFnData) => TData;
|
|
38
|
+
readonly stream?: StreamOptions<TQueryFnData, never>;
|
|
39
|
+
}
|
|
40
|
+
export interface StreamOptions<TData, TChunk> {
|
|
41
|
+
/** The data before the first chunk. */
|
|
42
|
+
readonly initial: TData;
|
|
43
|
+
/** Fold a chunk into the data. */
|
|
44
|
+
readonly reduce: (data: TData, chunk: TChunk) => TData;
|
|
45
|
+
}
|
|
46
|
+
type Awaitable<T> = PromiseLike<T> | T;
|
|
47
|
+
/**
|
|
48
|
+
* `T` as a conditional type, so a builder infers its data type from the
|
|
49
|
+
* `queryFn` alone: an annotated `select` or `getNextPageParam` parameter
|
|
50
|
+
* doesn't widen it.
|
|
51
|
+
*/
|
|
52
|
+
export type FromQueryFn<T> = T extends unknown ? T : never;
|
|
53
|
+
/** `queryOptions`, with `meta` checked against the root `TTypes`. */
|
|
54
|
+
export interface QueryOptionsBuilder<TTypes extends RootTypes> {
|
|
55
|
+
<const TKey extends QueryKey, TChunk, TData>(options: BaseOptions<TKey, TTypes> & {
|
|
56
|
+
readonly queryFn: (context: QueryFunctionContext<TKey>) => AsyncIterable<TChunk>;
|
|
57
|
+
readonly stream: StreamOptions<TData, TChunk>;
|
|
58
|
+
}): QueryOptions<TKey, TData, TData, TTypes>;
|
|
59
|
+
<const TKey extends QueryKey, TQueryFnData, TData = TQueryFnData>(options: BaseOptions<TKey, TTypes> & {
|
|
60
|
+
readonly queryFn: (context: QueryFunctionContext<TKey>) => Awaitable<TQueryFnData>;
|
|
61
|
+
readonly select?: (data: FromQueryFn<TQueryFnData>) => TData;
|
|
62
|
+
}): QueryOptions<TKey, TQueryFnData, TData, TTypes>;
|
|
219
63
|
}
|
|
220
|
-
export type AnyQueryOptions = QueryOptions<{
|
|
221
|
-
data: unknown;
|
|
222
|
-
error: unknown;
|
|
223
|
-
services: unknown;
|
|
224
|
-
}> | InfiniteQueryOptions<{
|
|
225
|
-
error: unknown;
|
|
226
|
-
page: unknown;
|
|
227
|
-
pageParam: unknown;
|
|
228
|
-
services: unknown;
|
|
229
|
-
}>;
|
|
230
64
|
/**
|
|
231
65
|
* Typed options for a query factory:
|
|
232
66
|
*
|
|
233
67
|
* ```ts
|
|
234
|
-
* export
|
|
235
|
-
*
|
|
236
|
-
* queryKey:
|
|
237
|
-
* queryFn: () =>
|
|
68
|
+
* export const issueQuery = (input: { id: number }) =>
|
|
69
|
+
* queryOptions({
|
|
70
|
+
* queryKey: issues("byId", input),
|
|
71
|
+
* queryFn: ({ signal }) => getIssue(input.id, { signal }),
|
|
238
72
|
* });
|
|
239
|
-
* }
|
|
240
73
|
* ```
|
|
241
74
|
*
|
|
242
|
-
* A `queryFn`
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* `error` out (`ErrorOf` is `unknown`).
|
|
75
|
+
* A `queryFn` that returns an async iterable is a stream: pass `stream` to
|
|
76
|
+
* fold its chunks into the data. Readers get the data after the first chunk,
|
|
77
|
+
* and every later chunk updates it in place.
|
|
246
78
|
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* types, and a handle of one doesn't type-check where the other's goes.
|
|
250
|
-
*
|
|
251
|
-
* The type parameters are only there for TypeScript to infer the types bag
|
|
252
|
-
* from `queryFn` and `queryKey`; it can't infer a bag's members.
|
|
253
|
-
*/
|
|
254
|
-
export declare function queryOptions<TData, TError = unknown, TServices = never, const TKey extends QueryKey = QueryKey>(options: Omit<QueryOptions<{
|
|
255
|
-
data: TData;
|
|
256
|
-
error: TError;
|
|
257
|
-
key: TKey;
|
|
258
|
-
services: TServices;
|
|
259
|
-
}>, "kind">): QueryOptions<QueryTypesOf<TData, TError, TServices, TKey>>;
|
|
260
|
-
/**
|
|
261
|
-
* Typed options for a paged query factory. The page type is inferred from
|
|
262
|
-
* `queryFn`, as in {@link queryOptions}. So is an Effect `queryFn`'s error;
|
|
263
|
-
* a promise or a plain value leaves `error` out. The key's literal type is
|
|
264
|
-
* kept, as in {@link queryOptions}.
|
|
79
|
+
* Its `meta` is any record. To check `meta` against a client's links and
|
|
80
|
+
* features, use the builder {@link bindQueryOptions} returns.
|
|
265
81
|
*/
|
|
266
|
-
export declare
|
|
267
|
-
error: TError;
|
|
268
|
-
key: TKey;
|
|
269
|
-
page: TPage;
|
|
270
|
-
pageParam: TPageParam;
|
|
271
|
-
services: TServices;
|
|
272
|
-
}>, "kind">): InfiniteQueryOptions<InfiniteQueryTypesOf<TPage, TPageParam, TError, TServices, TKey>>;
|
|
273
|
-
interface FactoryResult {
|
|
274
|
-
readonly kind: "infinite" | "query";
|
|
275
|
-
readonly queryKey: QueryKey;
|
|
276
|
-
}
|
|
82
|
+
export declare const queryOptions: QueryOptionsBuilder<DefaultTypes>;
|
|
277
83
|
/**
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
* argument is the query's input, and a handle carries it.
|
|
84
|
+
* `queryOptions` bound to a root: `meta` takes the fields the root's links
|
|
85
|
+
* and features declare, and verbs take only that root's clients. `T` is the
|
|
86
|
+
* client's type, or the type of a function that makes it. Bind once per app:
|
|
282
87
|
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
88
|
+
* ```ts
|
|
89
|
+
* // raf.ts
|
|
90
|
+
* export const queryOptions = bindQueryOptions<typeof makeQueryClient>();
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* It returns `queryOptions` itself; only the types change.
|
|
94
|
+
*/
|
|
95
|
+
export declare function bindQueryOptions<T>(): QueryOptionsBuilder<RootOf<T>>;
|
|
96
|
+
/**
|
|
97
|
+
* A function of the query's input that returns its options. The input is a
|
|
98
|
+
* method parameter typed `unknown`, which TypeScript checks bivariantly:
|
|
99
|
+
* every factory fits, and an inline generic factory maker passed where a
|
|
100
|
+
* `QueryFactory` is expected infers its own type parameters instead of
|
|
101
|
+
* `never`.
|
|
102
|
+
*/
|
|
103
|
+
export type QueryFactory = {
|
|
104
|
+
factory(input: unknown): {
|
|
105
|
+
readonly queryFn: (context: never) => unknown;
|
|
106
|
+
readonly queryKey: QueryKey;
|
|
107
|
+
};
|
|
108
|
+
}["factory"];
|
|
109
|
+
/** A factory whose query has one value, not pages: what `useQuery` reads. */
|
|
110
|
+
export type SingleQueryFactory = {
|
|
111
|
+
factory(input: unknown): ReturnType<QueryFactory> & {
|
|
112
|
+
readonly getNextPageParam?: never;
|
|
113
|
+
};
|
|
114
|
+
}["factory"];
|
|
115
|
+
/** A factory of paged queries (`infiniteQueryOptions`): what `useInfiniteQuery` reads. */
|
|
116
|
+
export type InfiniteQueryFactory = {
|
|
117
|
+
factory(input: unknown): ReturnType<QueryFactory> & {
|
|
118
|
+
readonly getNextPageParam: (...args: never) => unknown;
|
|
119
|
+
};
|
|
120
|
+
}["factory"];
|
|
121
|
+
/** What a reader gets: the `select`ed data, or else the `queryFn`'s. */
|
|
122
|
+
export type DataOf<TFactory extends QueryFactory> = ReturnType<TFactory> extends {
|
|
123
|
+
readonly [dataTag]?: infer TData;
|
|
124
|
+
} ? TData : never;
|
|
125
|
+
/** A factory's input: its first parameter, or `undefined` if it takes none. */
|
|
304
126
|
export type InputOf<TFactory extends QueryFactory> = Parameters<TFactory> extends [] ? undefined : Parameters<TFactory>[0];
|
|
305
|
-
/**
|
|
306
|
-
export type InputArgs<TFactory extends QueryFactory> = []
|
|
307
|
-
/**
|
|
308
|
-
export type
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
* particular query.
|
|
314
|
-
*/
|
|
315
|
-
export type DataOf<TFactory extends QueryFactory> = ReturnType<TFactory> extends InfiniteQueryOptions<infer TTypes> ? InfiniteData<{
|
|
316
|
-
page: TTypes["page"];
|
|
317
|
-
pageParam: TTypes["pageParam"];
|
|
318
|
-
}> : ReturnType<TFactory> extends QueryOptions<infer TTypes> ? TTypes["data"] : unknown;
|
|
319
|
-
/**
|
|
320
|
-
* The error a factory's request fails with: the `queryFn`'s Effect error
|
|
321
|
-
* type, or `unknown` for promises and plain values.
|
|
322
|
-
*/
|
|
323
|
-
export type ErrorOf<TFactory extends QueryFactory> = ReturnType<TFactory> extends InfiniteQueryOptions<infer TTypes> ? ErrorIn<TTypes> : ReturnType<TFactory> extends QueryOptions<infer TTypes> ? ErrorIn<TTypes> : unknown;
|
|
324
|
-
/**
|
|
325
|
-
* The services a factory's `queryFn` Effect needs: what `ensure`, `fetch`,
|
|
326
|
-
* `prefetch`, `getQuery` and `watch` require. `never` for promises and plain
|
|
327
|
-
* values, and for a factory of no particular query.
|
|
328
|
-
*/
|
|
329
|
-
export type ServicesOf<TFactory extends QueryFactory> = ReturnType<TFactory> extends InfiniteQueryOptions<infer TTypes> ? ServicesIn<TTypes> : ReturnType<TFactory> extends QueryOptions<infer TTypes> ? ServicesIn<TTypes> : never;
|
|
330
|
-
/** Page type of a paged factory. */
|
|
331
|
-
export type PageOf<TFactory extends QueryFactory> = ReturnType<TFactory> extends InfiniteQueryOptions<infer TTypes> ? TTypes["page"] : never;
|
|
332
|
-
/**
|
|
333
|
-
* `ensure` / `fetch` options, for {@link PagedQueryFactory paged factories}
|
|
334
|
-
* only. Not generic: an options type that depends on the factory's type stops
|
|
335
|
-
* a generic factory maker called inline from inferring.
|
|
336
|
-
*/
|
|
337
|
-
export interface LoadOptions {
|
|
338
|
-
/** Load this many pages up front (default 1). */
|
|
339
|
-
readonly pages?: number;
|
|
340
|
-
}
|
|
341
|
-
declare const factoryType: unique symbol;
|
|
342
|
-
/**
|
|
343
|
-
* The serializable reference a loader or server component hands to the
|
|
344
|
-
* component that reads the query. It holds no functions.
|
|
345
|
-
*/
|
|
346
|
-
export interface QueryHandle<TFactory extends QueryFactory = QueryFactory> {
|
|
347
|
-
/** Type-only: ties the handle to its factory. Never present at runtime. */
|
|
348
|
-
readonly [factoryType]?: TFactory;
|
|
349
|
-
/** The factory's input; `unknown` on a handle of no particular factory. */
|
|
350
|
-
readonly input: InputOf<TFactory>;
|
|
351
|
-
readonly key: QueryKey;
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* A handle from `ensure` or `fetch`, with the data they waited for. `data`
|
|
355
|
-
* is a snapshot from when the handle was returned; components read the live
|
|
356
|
-
* entry with `useQuery`.
|
|
357
|
-
*/
|
|
358
|
-
export interface QueryHandleWithData<TFactory extends QueryFactory = QueryFactory> extends QueryHandle<TFactory> {
|
|
359
|
-
readonly data: DataOf<TFactory>;
|
|
360
|
-
}
|
|
127
|
+
/** The input arguments of a factory: none, or its input. */
|
|
128
|
+
export type InputArgs<TFactory extends QueryFactory> = Parameters<TFactory> extends [] ? [] : Parameters<TFactory> extends [infer TInput, ...Array<unknown>] ? [input: TInput] : [input?: Parameters<TFactory>[0]];
|
|
129
|
+
/** A factory's key type, the way handles carry it. */
|
|
130
|
+
export type KeyOf<TFactory extends QueryFactory> = ReturnType<TFactory>["queryKey"];
|
|
131
|
+
/** The root a factory's builder is bound to; any root for an unbound one. */
|
|
132
|
+
export type RootOfFactory<TFactory extends QueryFactory> = ReturnType<TFactory> extends {
|
|
133
|
+
readonly "~root"?: RootTag<infer TTypes>;
|
|
134
|
+
} ? TTypes extends DefaultTypes ? AnyRoot : TTypes : AnyRoot;
|
|
361
135
|
//#endregion
|
package/dist/options.mjs
CHANGED
|
@@ -3,50 +3,39 @@
|
|
|
3
3
|
* Typed options for a query factory:
|
|
4
4
|
*
|
|
5
5
|
* ```ts
|
|
6
|
-
* export
|
|
7
|
-
*
|
|
8
|
-
* queryKey:
|
|
9
|
-
* queryFn: () =>
|
|
6
|
+
* export const issueQuery = (input: { id: number }) =>
|
|
7
|
+
* queryOptions({
|
|
8
|
+
* queryKey: issues("byId", input),
|
|
9
|
+
* queryFn: ({ signal }) => getIssue(input.id, { signal }),
|
|
10
10
|
* });
|
|
11
|
-
* }
|
|
12
11
|
* ```
|
|
13
12
|
*
|
|
14
|
-
* A `queryFn`
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* `error` out (`ErrorOf` is `unknown`).
|
|
13
|
+
* A `queryFn` that returns an async iterable is a stream: pass `stream` to
|
|
14
|
+
* fold its chunks into the data. Readers get the data after the first chunk,
|
|
15
|
+
* and every later chunk updates it in place.
|
|
18
16
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* types, and a handle of one doesn't type-check where the other's goes.
|
|
22
|
-
*
|
|
23
|
-
* The type parameters are only there for TypeScript to infer the types bag
|
|
24
|
-
* from `queryFn` and `queryKey`; it can't infer a bag's members.
|
|
17
|
+
* Its `meta` is any record. To check `meta` against a client's links and
|
|
18
|
+
* features, use the builder {@link bindQueryOptions} returns.
|
|
25
19
|
*/
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
...options,
|
|
29
|
-
kind: "query"
|
|
30
|
-
};
|
|
31
|
-
}
|
|
20
|
+
const queryOptions = (options) => options;
|
|
32
21
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
22
|
+
* `queryOptions` bound to a root: `meta` takes the fields the root's links
|
|
23
|
+
* and features declare, and verbs take only that root's clients. `T` is the
|
|
24
|
+
* client's type, or the type of a function that makes it. Bind once per app:
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* // raf.ts
|
|
28
|
+
* export const queryOptions = bindQueryOptions<typeof makeQueryClient>();
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* It returns `queryOptions` itself; only the types change.
|
|
37
32
|
*/
|
|
38
|
-
function
|
|
39
|
-
return
|
|
40
|
-
...options,
|
|
41
|
-
kind: "infinite"
|
|
42
|
-
};
|
|
33
|
+
function bindQueryOptions() {
|
|
34
|
+
return queryOptions;
|
|
43
35
|
}
|
|
44
|
-
/**
|
|
45
|
-
|
|
46
|
-
* `InputArgs<TFactory>`.
|
|
47
|
-
*/
|
|
48
|
-
function optionsFor(factory, input) {
|
|
36
|
+
/** Call a factory with an input its caller's types already checked. */
|
|
37
|
+
function optionsOf(factory, input) {
|
|
49
38
|
return factory(input);
|
|
50
39
|
}
|
|
51
40
|
//#endregion
|
|
52
|
-
export {
|
|
41
|
+
export { bindQueryOptions, optionsOf, queryOptions };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Feature, Link } from "./client.mjs";
|
|
2
|
+
import { FocusRefetchMeta } from "./features/focus-refetch/focus-refetch.mjs";
|
|
3
|
+
import { ReconnectRefetchMeta } from "./features/reconnect-refetch/reconnect-refetch.mjs";
|
|
4
|
+
import { PollingMeta } from "./features/polling/polling.mjs";
|
|
5
|
+
import { RetryMeta } from "./links/retry/retry.mjs";
|
|
6
|
+
//#region src/presets.d.ts
|
|
7
|
+
/** What `recommended()` returns: its parts keep the `meta` they declare. */
|
|
8
|
+
export interface Recommended {
|
|
9
|
+
readonly features: readonly [Feature<{
|
|
10
|
+
readonly meta: FocusRefetchMeta;
|
|
11
|
+
}>, Feature<{
|
|
12
|
+
readonly meta: ReconnectRefetchMeta;
|
|
13
|
+
}>, Feature<{
|
|
14
|
+
readonly meta: PollingMeta;
|
|
15
|
+
}>];
|
|
16
|
+
readonly links: readonly [Link<{
|
|
17
|
+
readonly meta: RetryMeta;
|
|
18
|
+
}>];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The behaviors most apps want: retries, refetching on focus and reconnect,
|
|
22
|
+
* and polling. Spread it into the config:
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* createQueryClient({ ...recommended(), staleTime: 30_000 });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function recommended(): Recommended;
|
|
29
|
+
//#endregion
|
package/dist/presets.mjs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { focusRefetch } from "./features/focus-refetch/focus-refetch.mjs";
|
|
2
|
+
import { reconnectRefetch } from "./features/reconnect-refetch/reconnect-refetch.mjs";
|
|
3
|
+
import { polling } from "./features/polling/polling.mjs";
|
|
4
|
+
import { retry } from "./links/retry/retry.mjs";
|
|
5
|
+
//#region src/presets.ts
|
|
6
|
+
/**
|
|
7
|
+
* The behaviors most apps want: retries, refetching on focus and reconnect,
|
|
8
|
+
* and polling. Spread it into the config:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* createQueryClient({ ...recommended(), staleTime: 30_000 });
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
function recommended() {
|
|
15
|
+
return {
|
|
16
|
+
features: [
|
|
17
|
+
focusRefetch(),
|
|
18
|
+
reconnectRefetch(),
|
|
19
|
+
polling()
|
|
20
|
+
],
|
|
21
|
+
links: [retry()]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { recommended };
|