@raf-query/core 0.13.2 → 0.14.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 +11 -1
- package/README.md +8 -5
- package/dist/client.d.mts +99 -72
- package/dist/client.mjs +19 -36
- package/dist/entry.mjs +18 -9
- package/dist/features/focus-refetch/focus-refetch.d.mts +13 -9
- package/dist/features/focus-refetch/focus-refetch.mjs +4 -4
- package/dist/features/polling/polling.d.mts +13 -9
- package/dist/features/polling/polling.mjs +6 -6
- package/dist/features/reconnect-refetch/reconnect-refetch.d.mts +13 -9
- package/dist/features/reconnect-refetch/reconnect-refetch.mjs +4 -4
- package/dist/features/shared.mjs +8 -6
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +2 -2
- package/dist/infinite/infinite.d.mts +17 -15
- package/dist/infinite/infinite.mjs +5 -4
- package/dist/internal.d.mts +3 -7
- package/dist/keys/targets.d.mts +7 -8
- package/dist/keys/targets.mjs +6 -5
- package/dist/links/retry/retry.d.mts +14 -10
- package/dist/links/retry/retry.mjs +5 -5
- package/dist/links/timeout/timeout.d.mts +2 -2
- package/dist/links/timeout/timeout.mjs +3 -2
- package/dist/load.d.mts +9 -2
- package/dist/options.d.mts +61 -39
- package/dist/options.mjs +15 -6
- package/dist/presets.d.mts +9 -20
- package/dist/presets.mjs +8 -10
- package/dist/root.d.mts +86 -40
- package/dist/verbs.d.mts +8 -9
- package/package.json +1 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { part } from "../../client.mjs";
|
|
2
2
|
import { refetchStaleReads } from "../shared.mjs";
|
|
3
3
|
//#region src/features/reconnect-refetch/reconnect-refetch.ts
|
|
4
4
|
/**
|
|
5
5
|
* Refetch read, stale queries when the browser comes back online, except
|
|
6
|
-
* those with `
|
|
6
|
+
* those with `refetchOnReconnect: false`.
|
|
7
7
|
*
|
|
8
8
|
* @see https://raf-query.katt.dev/docs/testing#focus-and-the-network
|
|
9
9
|
*/
|
|
10
10
|
function reconnectRefetch() {
|
|
11
|
-
return
|
|
11
|
+
return part({ setup: (client, signal) => {
|
|
12
12
|
window.addEventListener("online", () => refetchStaleReads(client, "refetchOnReconnect"), { signal });
|
|
13
|
-
});
|
|
13
|
+
} });
|
|
14
14
|
}
|
|
15
15
|
//#endregion
|
|
16
16
|
export { reconnectRefetch };
|
package/dist/features/shared.mjs
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { isObject } from "../guards.mjs";
|
|
2
2
|
import { fetchEntry, isStale } from "../entry.mjs";
|
|
3
3
|
//#region src/features/shared.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
|
|
4
|
+
/** An option a part declares, for the entry: the query's, or else the client's default. */
|
|
5
|
+
function optionOf(entry, name) {
|
|
6
|
+
for (const options of [entry.options, entry.client.config.defaults]) if (isObject(options) && name in options) {
|
|
7
|
+
const fields = options;
|
|
8
|
+
if (fields[name] !== void 0) return fields[name];
|
|
9
|
+
}
|
|
8
10
|
}
|
|
9
11
|
function refetchStaleReads(client, optOut) {
|
|
10
|
-
for (const entry of client["~entries"].values()) if (entry.readers.size > 0 && isStale(entry) &&
|
|
12
|
+
for (const entry of client["~entries"].values()) if (entry.readers.size > 0 && isStale(entry) && optionOf(entry, optOut) !== false) fetchEntry(entry);
|
|
11
13
|
}
|
|
12
14
|
//#endregion
|
|
13
|
-
export {
|
|
15
|
+
export { optionOf, refetchStaleReads };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { Group, QueryKey, group } from "./keys/keys.mjs";
|
|
2
|
-
import { QueryMeta } from "./root.mjs";
|
|
3
2
|
import { QueryInfo, Target } from "./keys/targets.mjs";
|
|
4
|
-
import {
|
|
3
|
+
import { Optional, RootOf } from "./root.mjs";
|
|
4
|
+
import { CoreOptions, DataOf, InfiniteQueryFactory, InputOf, OptionsOf, QueryFactory, QueryFunctionContext, QueryOptions, QueryOptionsBuilder, SingleQueryFactory, StreamOptions, bindQueryOptions, queryOptions } from "./options.mjs";
|
|
5
5
|
import { Thenable } from "./thenable.mjs";
|
|
6
6
|
import { abortError } from "./entry.mjs";
|
|
7
|
-
import { Clock,
|
|
8
|
-
import { focusRefetch } from "./features/focus-refetch/focus-refetch.mjs";
|
|
9
|
-
import { reconnectRefetch } from "./features/reconnect-refetch/reconnect-refetch.mjs";
|
|
10
|
-
import { polling } from "./features/polling/polling.mjs";
|
|
7
|
+
import { Clock, Operation, Part, QueryClient, QueryClientConfig, createQueryClient, part } from "./client.mjs";
|
|
8
|
+
import { FocusRefetch, focusRefetch } from "./features/focus-refetch/focus-refetch.mjs";
|
|
9
|
+
import { ReconnectRefetch, reconnectRefetch } from "./features/reconnect-refetch/reconnect-refetch.mjs";
|
|
10
|
+
import { Polling, polling } from "./features/polling/polling.mjs";
|
|
11
11
|
import { DehydrateOptions, DehydratedEntry, DehydratedResult, DehydratedState, DehydratedStream, RedactedError, canDehydrate, dehydrate, dehydrateStream, hydrate } from "./hydration/hydration.mjs";
|
|
12
12
|
import { InfiniteData, InfiniteQueryFunctionContext, InfiniteQueryOptions, InfiniteQueryOptionsBuilder, bindInfiniteQueryOptions, infiniteQueryOptions } from "./infinite/infinite.mjs";
|
|
13
13
|
import { ClientFor, PartialInput, getData, invalidateAll, invalidateMany, invalidateOne, isFetching, removeAll, removeMany, removeOne, resetAll, resetMany, resetOne, setData } from "./verbs.mjs";
|
|
14
14
|
import { PageControls, PageDirection, PageState, fetchNextPage, fetchPreviousPage, hasNextPage, hasPreviousPage } from "./infinite/paging.mjs";
|
|
15
|
-
import { RetryOptions, retry } from "./links/retry/retry.mjs";
|
|
15
|
+
import { Retry, RetryOptions, retry } from "./links/retry/retry.mjs";
|
|
16
16
|
import { QueryTimeoutError, timeout } from "./links/timeout/timeout.mjs";
|
|
17
17
|
import { LoadEntry, LoadEntryOptions, Loaded, QueryHandle, load, prefetch, revalidate, skipToken, swr, waterfallHandle } from "./load.mjs";
|
|
18
18
|
import { Recommended, recommended } from "./presets.mjs";
|
|
19
|
-
export { type ClientFor, type Clock, type DataOf, type DehydrateOptions, type DehydratedEntry, type DehydratedResult, type DehydratedState, type DehydratedStream, type
|
|
19
|
+
export { type ClientFor, type Clock, type CoreOptions, type DataOf, type DehydrateOptions, type DehydratedEntry, type DehydratedResult, type DehydratedState, type DehydratedStream, type FocusRefetch, type Group, type InfiniteData, type InfiniteQueryFactory, type InfiniteQueryFunctionContext, type InfiniteQueryOptions, type InfiniteQueryOptionsBuilder, type InputOf, type LoadEntry, type LoadEntryOptions, type Loaded, type Operation, type Optional, type OptionsOf, type PageControls, type PageDirection, type PageState, type Part, type PartialInput, type Polling, type QueryClient, type QueryClientConfig, type QueryFactory, type QueryFunctionContext, type QueryHandle, type QueryInfo, type QueryKey, type QueryOptions, type QueryOptionsBuilder, QueryTimeoutError, type Recommended, type ReconnectRefetch, RedactedError, type Retry, type RetryOptions, type RootOf, type SingleQueryFactory, type StreamOptions, type Target, type Thenable, abortError, bindInfiniteQueryOptions, bindQueryOptions, canDehydrate, createQueryClient, dehydrate, dehydrateStream, fetchNextPage, fetchPreviousPage, focusRefetch, getData, group, hasNextPage, hasPreviousPage, hydrate, infiniteQueryOptions, invalidateAll, invalidateMany, invalidateOne, isFetching, load, part, polling, prefetch, queryOptions, recommended, reconnectRefetch, removeAll, removeMany, removeOne, resetAll, resetMany, resetOne, retry, revalidate, setData, skipToken, swr, timeout, waterfallHandle };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createQueryClient,
|
|
1
|
+
import { createQueryClient, part } from "./client.mjs";
|
|
2
2
|
import { group } from "./keys/keys.mjs";
|
|
3
3
|
import { bindQueryOptions, queryOptions } from "./options.mjs";
|
|
4
4
|
import { abortError } from "./entry.mjs";
|
|
@@ -13,4 +13,4 @@ import { QueryTimeoutError, timeout } from "./links/timeout/timeout.mjs";
|
|
|
13
13
|
import { load, prefetch, revalidate, skipToken, swr, waterfallHandle } from "./load.mjs";
|
|
14
14
|
import { recommended } from "./presets.mjs";
|
|
15
15
|
import { getData, invalidateAll, invalidateMany, invalidateOne, isFetching, removeAll, removeMany, removeOne, resetAll, resetMany, resetOne, setData } from "./verbs.mjs";
|
|
16
|
-
export { QueryTimeoutError, RedactedError, abortError, bindInfiniteQueryOptions, bindQueryOptions, canDehydrate, createQueryClient, dehydrate, dehydrateStream,
|
|
16
|
+
export { QueryTimeoutError, RedactedError, abortError, bindInfiniteQueryOptions, bindQueryOptions, canDehydrate, createQueryClient, dehydrate, dehydrateStream, fetchNextPage, fetchPreviousPage, focusRefetch, getData, group, hasNextPage, hasPreviousPage, hydrate, infiniteQueryOptions, invalidateAll, invalidateMany, invalidateOne, isFetching, load, part, polling, prefetch, queryOptions, recommended, reconnectRefetch, removeAll, removeMany, removeOne, resetAll, resetMany, resetOne, retry, revalidate, setData, skipToken, swr, timeout, waterfallHandle };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryKey } from "../keys/keys.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { NoParts, RootOf, RootTypes, SetsOf } from "../root.mjs";
|
|
3
3
|
import { BaseOptions, FromQueryFn, QueryFunctionContext, QueryOptions } from "../options.mjs";
|
|
4
4
|
import { Operation } from "../client.mjs";
|
|
5
5
|
//#region src/infinite/infinite.d.ts
|
|
@@ -17,12 +17,12 @@ export interface InfiniteData<TPage, TParam = unknown> {
|
|
|
17
17
|
*
|
|
18
18
|
* @see https://raf-query.katt.dev/docs/infinite-queries
|
|
19
19
|
*/
|
|
20
|
-
export
|
|
20
|
+
export type InfiniteQueryFunctionContext<TKey extends QueryKey, TParam, TTypes extends RootTypes = NoParts> = QueryFunctionContext<TKey, TTypes> & {
|
|
21
21
|
readonly direction: "backward" | "forward";
|
|
22
22
|
readonly pageParam: TParam;
|
|
23
|
-
}
|
|
23
|
+
};
|
|
24
24
|
type PageParamFn<TPage, TParam> = (page: TPage, pages: ReadonlyArray<TPage>, pageParam: TParam) => TParam | null | undefined;
|
|
25
|
-
interface InfiniteOptions<TKey extends QueryKey, TPage, TParam, TData
|
|
25
|
+
interface InfiniteOptions<TKey extends QueryKey, TPage, TParam, TData> extends BaseOptions<TKey> {
|
|
26
26
|
readonly getNextPageParam: PageParamFn<TPage, TParam>;
|
|
27
27
|
readonly getPreviousPageParam?: PageParamFn<TPage, TParam>;
|
|
28
28
|
readonly initialPageParam: TParam;
|
|
@@ -45,17 +45,18 @@ interface InfiniteOptions<TKey extends QueryKey, TPage, TParam, TData, TTypes ex
|
|
|
45
45
|
*
|
|
46
46
|
* @see https://raf-query.katt.dev/docs/infinite-queries
|
|
47
47
|
*/
|
|
48
|
-
export type InfiniteQueryOptions<TKey extends QueryKey = QueryKey, TPage = unknown, TParam = unknown, TData = InfiniteData<TPage, TParam>, TTypes extends RootTypes = RootTypes> = QueryOptions<TKey, InfiniteData<TPage, TParam>, TData, TTypes> & Pick<InfiniteOptions<TKey, TPage, TParam, TData
|
|
48
|
+
export type InfiniteQueryOptions<TKey extends QueryKey = QueryKey, TPage = unknown, TParam = unknown, TData = InfiniteData<TPage, TParam>, TTypes extends RootTypes = RootTypes> = QueryOptions<TKey, InfiniteData<TPage, TParam>, TData, TTypes> & Pick<InfiniteOptions<TKey, TPage, TParam, TData>, "getNextPageParam" | "getPreviousPageParam" | "initialPageParam" | "maxPages"> & {
|
|
49
49
|
readonly "~run": (op: Operation) => Promise<unknown>;
|
|
50
50
|
};
|
|
51
51
|
/**
|
|
52
|
-
* `infiniteQueryOptions
|
|
52
|
+
* `infiniteQueryOptions` for a root: `TTypes` is what the factories it
|
|
53
|
+
* builds need of a client, and `TSets` the options they can set.
|
|
53
54
|
*
|
|
54
|
-
* @see https://raf-query.katt.dev/docs/links-and-features#typing-
|
|
55
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
55
56
|
*/
|
|
56
|
-
export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes> {
|
|
57
|
-
<const TKey extends QueryKey, TPage, TParam, TData = InfiniteData<TPage, TParam>>(options: InfiniteOptions<TKey, FromQueryFn<TPage>, TParam, TData
|
|
58
|
-
readonly queryFn: (context: InfiniteQueryFunctionContext<TKey, TParam>) => PromiseLike<TPage> | TPage;
|
|
57
|
+
export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes, TSets extends RootTypes = TTypes> {
|
|
58
|
+
<const TKey extends QueryKey, TPage, TParam, TData = InfiniteData<TPage, TParam>>(options: InfiniteOptions<TKey, FromQueryFn<TPage>, TParam, TData> & Partial<TSets["options"]> & {
|
|
59
|
+
readonly queryFn: (context: InfiniteQueryFunctionContext<TKey, TParam, TTypes>) => PromiseLike<TPage> | TPage;
|
|
59
60
|
}): InfiniteQueryOptions<TKey, TPage, TParam, TData, TTypes>;
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
@@ -72,12 +73,13 @@ export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes> {
|
|
|
72
73
|
* });
|
|
73
74
|
* ```
|
|
74
75
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
76
|
+
* It takes the core's options only. For the options and the `queryFn`
|
|
77
|
+
* context a client's parts declare, use the builder
|
|
78
|
+
* {@link bindInfiniteQueryOptions} returns.
|
|
77
79
|
*
|
|
78
80
|
* @see https://raf-query.katt.dev/docs/infinite-queries
|
|
79
81
|
*/
|
|
80
|
-
export declare const infiniteQueryOptions: InfiniteQueryOptionsBuilder<
|
|
82
|
+
export declare const infiniteQueryOptions: InfiniteQueryOptionsBuilder<NoParts>;
|
|
81
83
|
/**
|
|
82
84
|
* `infiniteQueryOptions` bound to a root, like `bindQueryOptions`. Bind it
|
|
83
85
|
* next to `queryOptions`, in apps that page:
|
|
@@ -87,7 +89,7 @@ export declare const infiniteQueryOptions: InfiniteQueryOptionsBuilder<DefaultTy
|
|
|
87
89
|
* export const infiniteQueryOptions = bindInfiniteQueryOptions<typeof makeQueryClient>();
|
|
88
90
|
* ```
|
|
89
91
|
*
|
|
90
|
-
* @see https://raf-query.katt.dev/docs/links-and-features#typing-
|
|
92
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
91
93
|
*/
|
|
92
|
-
export declare function bindInfiniteQueryOptions<T>(): InfiniteQueryOptionsBuilder<RootOf<T>>;
|
|
94
|
+
export declare function bindInfiniteQueryOptions<T>(): InfiniteQueryOptionsBuilder<RootOf<T>, SetsOf<T>>;
|
|
93
95
|
//#endregion
|
|
@@ -14,8 +14,9 @@ import { hashKey } from "../keys/keys.mjs";
|
|
|
14
14
|
* });
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* It takes the core's options only. For the options and the `queryFn`
|
|
18
|
+
* context a client's parts declare, use the builder
|
|
19
|
+
* {@link bindInfiniteQueryOptions} returns.
|
|
19
20
|
*
|
|
20
21
|
* @see https://raf-query.katt.dev/docs/infinite-queries
|
|
21
22
|
*/
|
|
@@ -33,7 +34,7 @@ const infiniteQueryOptions = (options) => ({
|
|
|
33
34
|
* export const infiniteQueryOptions = bindInfiniteQueryOptions<typeof makeQueryClient>();
|
|
34
35
|
* ```
|
|
35
36
|
*
|
|
36
|
-
* @see https://raf-query.katt.dev/docs/links-and-features#typing-
|
|
37
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
37
38
|
*/
|
|
38
39
|
function bindInfiniteQueryOptions() {
|
|
39
40
|
return infiniteQueryOptions;
|
|
@@ -65,9 +66,9 @@ function pageFor(data, pageParam) {
|
|
|
65
66
|
}
|
|
66
67
|
async function runPages(op, source) {
|
|
67
68
|
const fetchPage = (pageParam, direction) => Promise.resolve(source.queryFn({
|
|
69
|
+
...op.client.context,
|
|
68
70
|
client: op.client,
|
|
69
71
|
direction,
|
|
70
|
-
meta: op.meta,
|
|
71
72
|
pageParam,
|
|
72
73
|
queryKey: op.queryKey,
|
|
73
74
|
signal: op.signal
|
package/dist/internal.d.mts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { AnyFactory, hashKey } from "./keys/keys.mjs";
|
|
2
|
-
import { Decl, DefaultTypes, MetaOf, RootOf, RootTypes } from "./root.mjs";
|
|
3
2
|
import { AnyTarget } from "./keys/targets.mjs";
|
|
3
|
+
import { Decl, NoParts, Root, RootOf, RootOfParts, RootTypes, SetsOf } from "./root.mjs";
|
|
4
4
|
import { fulfilled, mapThenable, pending, rejected } from "./thenable.mjs";
|
|
5
5
|
import { Entry, EntryState, entryOf, fetchEntry, isBrowserOnly, isInvalidated, isStale, remove, reset, subscribeEntry } from "./entry.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { FocusRefetchMeta } from "./features/focus-refetch/focus-refetch.mjs";
|
|
8
|
-
import { ReconnectRefetchMeta } from "./features/reconnect-refetch/reconnect-refetch.mjs";
|
|
9
|
-
import { PollingMeta } from "./features/polling/polling.mjs";
|
|
6
|
+
import { AnyPart, ClientEvent, mount, systemClock } from "./client.mjs";
|
|
10
7
|
import { fetchPage, pageState } from "./infinite/paging.mjs";
|
|
11
|
-
import { RetryMeta } from "./links/retry/retry.mjs";
|
|
12
8
|
import { LoadRecord, isWaterfallHandle, loadsOf, readData, startIfStale } from "./load.mjs";
|
|
13
|
-
export { type AnyFactory, type
|
|
9
|
+
export { type AnyFactory, type AnyPart, type AnyTarget, type ClientEvent, type Decl, type Entry, type EntryState, type LoadRecord, type NoParts, type Root, type RootOf, type RootOfParts, type RootTypes, type SetsOf, entryOf, fetchEntry, fetchPage, fulfilled, hashKey, isBrowserOnly, isInvalidated, isStale, isWaterfallHandle, loadsOf, mapThenable, mount, pageState, pending, readData, rejected, remove, reset, startIfStale, subscribeEntry, systemClock };
|
package/dist/keys/targets.d.mts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { AnyFactory, Group, QueryKey } from "./keys.mjs";
|
|
2
|
-
import { QueryMeta } from "../root.mjs";
|
|
3
2
|
//#region src/keys/targets.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* What a target's `where` sees of a query.
|
|
6
5
|
*
|
|
7
6
|
* @see https://raf-query.katt.dev/docs/query-invalidation#matching-with-where
|
|
8
7
|
*/
|
|
9
|
-
export interface QueryInfo<
|
|
8
|
+
export interface QueryInfo<TOptions = object> {
|
|
10
9
|
/** The query's data, before `select`; `undefined` without data. */
|
|
11
10
|
readonly data: unknown;
|
|
12
11
|
readonly input: unknown;
|
|
13
|
-
/** The
|
|
14
|
-
readonly
|
|
12
|
+
/** The options its factory gave it. An entry only hydrated has `{}` until it's read. */
|
|
13
|
+
readonly options: TOptions;
|
|
15
14
|
readonly queryKey: QueryKey;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
@@ -19,16 +18,16 @@ export interface QueryInfo<TMeta = QueryMeta> {
|
|
|
19
18
|
* parameter the verb was called with.
|
|
20
19
|
*
|
|
21
20
|
* ```ts
|
|
22
|
-
* const ownedBy: Target<
|
|
21
|
+
* const ownedBy: Target<RootOf<Ownership>["options"], Team> = { where: (query, team) => query.options.owner === team };
|
|
23
22
|
* await invalidateMany(client, ownedBy, "editorial");
|
|
24
23
|
* ```
|
|
25
24
|
*
|
|
26
25
|
* @see https://raf-query.katt.dev/docs/query-invalidation#targets
|
|
27
26
|
*/
|
|
28
|
-
export interface Target<
|
|
29
|
-
readonly where: (query: QueryInfo<
|
|
27
|
+
export interface Target<TOptions = object, TParam = never> {
|
|
28
|
+
readonly where: (query: QueryInfo<TOptions>, param: TParam) => boolean;
|
|
30
29
|
}
|
|
31
|
-
/** A target of any
|
|
30
|
+
/** A target of any options and parameter. */
|
|
32
31
|
export interface AnyTarget {
|
|
33
32
|
readonly where: (query: never, param: never) => boolean;
|
|
34
33
|
}
|
package/dist/keys/targets.mjs
CHANGED
|
@@ -12,14 +12,15 @@ import { isPlainRecord } from "./keys.mjs";
|
|
|
12
12
|
* path, `drafts("byId", input)` is `["posts", "drafts", "byId", input]`.
|
|
13
13
|
* It matches every key that starts with its path, whoever built the key,
|
|
14
14
|
* so it covers its subgroups and their queries.
|
|
15
|
-
* - Any object with `where(query, param)`, typed by the
|
|
16
|
-
*
|
|
17
|
-
* are one, written in user code over a `
|
|
15
|
+
* - Any object with `where(query, param)`, typed by the options the
|
|
16
|
+
* client's parts declare: predicates over a query's key, input, options
|
|
17
|
+
* or data. Tags are one, written in user code over a `tags` option a
|
|
18
|
+
* part declares.
|
|
18
19
|
*
|
|
19
20
|
* Invalidation records a stamp per target. An entry is invalidated when a
|
|
20
21
|
* matching stamp is newer than the request its data came from. Entries with
|
|
21
22
|
* readers refetch at once; the rest are checked when they are next read,
|
|
22
|
-
* which always goes through their factory, so `where` sees their
|
|
23
|
+
* which always goes through their factory, so `where` sees their options.
|
|
23
24
|
*
|
|
24
25
|
* An entry that was only hydrated has no factory or input until it's read.
|
|
25
26
|
* A factory target covers it from that first read: invalidation through its
|
|
@@ -64,7 +65,7 @@ function infoOf(entry) {
|
|
|
64
65
|
return {
|
|
65
66
|
data: entry.state.data,
|
|
66
67
|
input: entry.input,
|
|
67
|
-
|
|
68
|
+
options: entry.options ?? {},
|
|
68
69
|
queryKey: entry.key
|
|
69
70
|
};
|
|
70
71
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Part } from "../../client.mjs";
|
|
2
2
|
//#region src/links/retry/retry.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* Options for {@link retry}.
|
|
@@ -6,28 +6,32 @@ import { Link } from "../../client.mjs";
|
|
|
6
6
|
* @see https://raf-query.katt.dev/docs/retries#options
|
|
7
7
|
*/
|
|
8
8
|
export interface RetryOptions {
|
|
9
|
-
/** Retries after the first attempt. A query's `
|
|
9
|
+
/** Retries after the first attempt. A query's `retry`, or the client's default for it, wins. Default 3. */
|
|
10
10
|
readonly attempts?: number;
|
|
11
11
|
/** Wait before retry `n` (0-based), in ms. Default: doubling from 1 s, at most 30 s. */
|
|
12
12
|
readonly delay?: (attempt: number) => number;
|
|
13
13
|
/** Whether an error is worth retrying. Default: every error but a thrown `Response`. */
|
|
14
14
|
readonly when?: (error: unknown) => boolean;
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
/**
|
|
17
|
+
* What `retry()` declares.
|
|
18
|
+
*
|
|
19
|
+
* @see https://raf-query.katt.dev/docs/retries
|
|
20
|
+
*/
|
|
21
|
+
export interface Retry {
|
|
22
|
+
readonly options: {
|
|
23
|
+
/** Attempts for this query, or `false`. */
|
|
24
|
+
readonly retry?: number | false;
|
|
25
|
+
};
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
28
|
* Retry failed requests. Thrown `Response`s (router redirects and
|
|
23
29
|
* not-founds) and cancelled requests aren't retried,
|
|
24
30
|
* server clients never retry, and a browser that is offline
|
|
25
31
|
* waits until it's back online before retrying. A query sets its own
|
|
26
|
-
* attempts with `
|
|
32
|
+
* attempts with `retry`.
|
|
27
33
|
*
|
|
28
34
|
* @see https://raf-query.katt.dev/docs/retries
|
|
29
35
|
*/
|
|
30
|
-
export declare function retry(options?: RetryOptions):
|
|
31
|
-
readonly meta: RetryMeta;
|
|
32
|
-
}>;
|
|
36
|
+
export declare function retry(options?: RetryOptions): Part<Retry>;
|
|
33
37
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { part } from "../../client.mjs";
|
|
2
2
|
import { isResponse } from "../../guards.mjs";
|
|
3
3
|
//#region src/links/retry/retry.ts
|
|
4
4
|
function wait(clock, ms, signal) {
|
|
@@ -31,13 +31,13 @@ const notThrownResponse = (error) => !isResponse(error);
|
|
|
31
31
|
* not-founds) and cancelled requests aren't retried,
|
|
32
32
|
* server clients never retry, and a browser that is offline
|
|
33
33
|
* waits until it's back online before retrying. A query sets its own
|
|
34
|
-
* attempts with `
|
|
34
|
+
* attempts with `retry`.
|
|
35
35
|
*
|
|
36
36
|
* @see https://raf-query.katt.dev/docs/retries
|
|
37
37
|
*/
|
|
38
38
|
function retry(options = {}) {
|
|
39
|
-
return link
|
|
40
|
-
const configured = op.
|
|
39
|
+
return part({ link: async (op, next) => {
|
|
40
|
+
const configured = op.options.retry;
|
|
41
41
|
const attempts = configured === false ? 0 : configured ?? options.attempts ?? 3;
|
|
42
42
|
if (op.client.isServer || attempts === 0) return next(op);
|
|
43
43
|
for (let attempt = 0;; attempt++) try {
|
|
@@ -47,7 +47,7 @@ function retry(options = {}) {
|
|
|
47
47
|
await wait(op.client.clock, (options.delay ?? defaultDelay)(attempt), op.signal);
|
|
48
48
|
await whenOnline(op.signal);
|
|
49
49
|
}
|
|
50
|
-
});
|
|
50
|
+
} });
|
|
51
51
|
}
|
|
52
52
|
//#endregion
|
|
53
53
|
export { retry };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Part } from "../../client.mjs";
|
|
2
2
|
//#region src/links/timeout/timeout.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* What a request that took too long fails with.
|
|
@@ -13,5 +13,5 @@ export declare class QueryTimeoutError extends Error {
|
|
|
13
13
|
*
|
|
14
14
|
* @see https://raf-query.katt.dev/docs/retries#timeouts
|
|
15
15
|
*/
|
|
16
|
-
export declare function timeout(ms: number):
|
|
16
|
+
export declare function timeout(ms: number): Part;
|
|
17
17
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { part } from "../../client.mjs";
|
|
1
2
|
//#region src/links/timeout/timeout.ts
|
|
2
3
|
/**
|
|
3
4
|
* What a request that took too long fails with.
|
|
@@ -13,7 +14,7 @@ var QueryTimeoutError = class extends Error {
|
|
|
13
14
|
* @see https://raf-query.katt.dev/docs/retries#timeouts
|
|
14
15
|
*/
|
|
15
16
|
function timeout(ms) {
|
|
16
|
-
return (op, next) => {
|
|
17
|
+
return part({ link: (op, next) => {
|
|
17
18
|
const controller = new AbortController();
|
|
18
19
|
const signal = AbortSignal.any([op.signal, controller.signal]);
|
|
19
20
|
return new Promise((resolve, reject) => {
|
|
@@ -29,7 +30,7 @@ function timeout(ms) {
|
|
|
29
30
|
op.client.clock.clearTimeout(handle);
|
|
30
31
|
});
|
|
31
32
|
});
|
|
32
|
-
};
|
|
33
|
+
} });
|
|
33
34
|
}
|
|
34
35
|
//#endregion
|
|
35
36
|
export { QueryTimeoutError, timeout };
|
package/dist/load.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RootTypes } from "./root.mjs";
|
|
2
|
+
import { DataOf, InputArgs, InputOf, KeyOf, QueryFactory, RootOfFactory } from "./options.mjs";
|
|
2
3
|
import { Entry } from "./entry.mjs";
|
|
3
4
|
import { QueryClient } from "./client.mjs";
|
|
4
5
|
//#region src/load.d.ts
|
|
@@ -84,6 +85,12 @@ type LoadEntries = Record<string, LoadEntry | typeof skipToken>;
|
|
|
84
85
|
type HandleOf<TEntry> = TEntry extends LoadEntry ? QueryHandle<TEntry["factory"]> : undefined;
|
|
85
86
|
type DataOfEntry<TEntry> = TEntry extends LoadEntry ? DataOf<TEntry["factory"]> : never;
|
|
86
87
|
type LoadedData<TEntries extends LoadEntries> = { [TName in keyof TEntries as TEntries[TName] extends LoadEntry<QueryFactory, "revalidate" | "swr"> ? TName : never]: DataOfEntry<TEntries[TName]>; };
|
|
88
|
+
/** In an error: the parts an entry's factory needs, which the client passed to `load` lacks. */
|
|
89
|
+
interface ClientLacksParts<TTypes extends RootTypes> {
|
|
90
|
+
readonly "~the client lacks parts this entry's factory needs": TTypes;
|
|
91
|
+
}
|
|
92
|
+
/** An entry, if the client has the parts its factory needs; else what it needs. */
|
|
93
|
+
type EntryFor<TTypes extends RootTypes, TEntry> = TEntry extends LoadEntry<infer TFactory> ? [TTypes] extends [RootOfFactory<TFactory>] ? TEntry : ClientLacksParts<RootOfFactory<TFactory>> : TEntry;
|
|
87
94
|
/**
|
|
88
95
|
* What `load` resolves to: a handle per entry (`undefined` for `skipToken`),
|
|
89
96
|
* and the data of `swr` and `revalidate` entries.
|
|
@@ -124,7 +131,7 @@ export declare function startIfStale(entry: Entry): void;
|
|
|
124
131
|
*
|
|
125
132
|
* @see https://raf-query.katt.dev/docs/starting-queries
|
|
126
133
|
*/
|
|
127
|
-
export declare function load<const TEntries extends LoadEntries>(client: QueryClient
|
|
134
|
+
export declare function load<TTypes extends RootTypes, const TEntries extends LoadEntries>(client: QueryClient<TTypes>, entries: TEntries & { readonly [TName in keyof TEntries]: EntryFor<TTypes, TEntries[TName]>; }): Promise<Loaded<TEntries>>;
|
|
128
135
|
/** Whether a handle came from `waterfallHandle()`: reading it is expected to fetch. */
|
|
129
136
|
export declare function isWaterfallHandle(handle: Pick<QueryHandle, "queryKey">): boolean;
|
|
130
137
|
/**
|
package/dist/options.d.mts
CHANGED
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
import { QueryKey } from "./keys/keys.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { NoParts, RootOf, RootTag, RootTypes, SetsOf } from "./root.mjs";
|
|
3
3
|
import { QueryClient } from "./client.mjs";
|
|
4
4
|
//#region src/options.d.ts
|
|
5
5
|
/**
|
|
6
|
-
* What a `queryFn` gets: the client making the request, the query's key
|
|
7
|
-
* `
|
|
6
|
+
* What a `queryFn` gets: the client making the request, the query's key and
|
|
7
|
+
* abort `signal`, and what the client's parts give every `queryFn`.
|
|
8
8
|
*
|
|
9
9
|
* @see https://raf-query.katt.dev/docs/query-functions#the-query-function-context
|
|
10
10
|
*/
|
|
11
|
-
export
|
|
11
|
+
export type QueryFunctionContext<TKey extends QueryKey = QueryKey, TTypes extends RootTypes = NoParts> = TTypes["context"] & {
|
|
12
12
|
/**
|
|
13
|
-
* The client making the request. A server makes one per request, so
|
|
14
|
-
*
|
|
15
|
-
* cookies.
|
|
13
|
+
* The client making the request. A server makes one per request, so
|
|
14
|
+
* what its parts give the context belongs to that request, such as an
|
|
15
|
+
* API client with the request's cookies.
|
|
16
16
|
*/
|
|
17
|
-
readonly client: QueryClient
|
|
18
|
-
/** The query's `meta`, typed by its root where the query is defined. */
|
|
19
|
-
readonly meta: object;
|
|
17
|
+
readonly client: QueryClient<TTypes>;
|
|
20
18
|
readonly queryKey: TKey;
|
|
21
19
|
/** Aborted when the request is restarted or its entry is removed. */
|
|
22
20
|
readonly signal: AbortSignal;
|
|
23
|
-
}
|
|
21
|
+
};
|
|
24
22
|
declare const dataTag: unique symbol;
|
|
25
23
|
declare const queryFnDataTag: unique symbol;
|
|
26
|
-
/**
|
|
27
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The per-query options the core reads, whatever parts the client has. A
|
|
26
|
+
* client's `defaults` set them for every query.
|
|
27
|
+
*
|
|
28
|
+
* @see https://raf-query.katt.dev/docs/important-defaults#changing-the-defaults
|
|
29
|
+
*/
|
|
30
|
+
export interface CoreOptions {
|
|
28
31
|
/** How long an entry with no reader stays cached. Default 5 minutes; never on the server. */
|
|
29
32
|
readonly gcTime?: number;
|
|
30
|
-
/**
|
|
31
|
-
* Settings for the root's links and features, and data for targets: the
|
|
32
|
-
* fields the root's parts declare, such as `retry` with the `retry()`
|
|
33
|
-
* link.
|
|
34
|
-
*/
|
|
35
|
-
readonly meta?: NoInfer<Partial<TTypes["meta"]>>;
|
|
36
|
-
/** A plain array, usually built by a `group()`. Handles keep its literal type. */
|
|
37
|
-
readonly queryKey: TKey;
|
|
38
33
|
/**
|
|
39
34
|
* `false` for a query only a browser can run (a permission, the service
|
|
40
35
|
* worker, `localStorage`): a server client never starts it, never sends
|
|
@@ -49,12 +44,29 @@ export interface BaseOptions<TKey extends QueryKey, TTypes extends RootTypes = R
|
|
|
49
44
|
/** Keep the deeply equal parts of new data, so they keep their identity. Default `true`. */
|
|
50
45
|
readonly structuralSharing?: boolean;
|
|
51
46
|
}
|
|
47
|
+
/** Options every query takes. */
|
|
48
|
+
export interface BaseOptions<TKey extends QueryKey> extends CoreOptions {
|
|
49
|
+
/** A plain array, usually built by a `group()`. Handles keep its literal type. */
|
|
50
|
+
readonly queryKey: TKey;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The options a builder bound to `T` lets a query set, beside its key and
|
|
54
|
+
* `queryFn`: the core's, and those `T`'s parts declare. For a fragment
|
|
55
|
+
* several factories share:
|
|
56
|
+
*
|
|
57
|
+
* ```ts
|
|
58
|
+
* const pinned = { retry: false, staleTime: Infinity } satisfies OptionsOf<typeof makeQueryClient>;
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
62
|
+
*/
|
|
63
|
+
export type OptionsOf<T> = CoreOptions & Partial<SetsOf<T>["options"]>;
|
|
52
64
|
/**
|
|
53
65
|
* What `queryOptions` and `infiniteQueryOptions` return.
|
|
54
66
|
*
|
|
55
67
|
* @see https://raf-query.katt.dev/docs/api-reference#query-factories
|
|
56
68
|
*/
|
|
57
|
-
export interface QueryOptions<TKey extends QueryKey = QueryKey, TQueryFnData = unknown, TData = TQueryFnData, TTypes extends RootTypes = RootTypes> extends BaseOptions<TKey
|
|
69
|
+
export interface QueryOptions<TKey extends QueryKey = QueryKey, TQueryFnData = unknown, TData = TQueryFnData, TTypes extends RootTypes = RootTypes> extends BaseOptions<TKey> {
|
|
58
70
|
/** Set by `infiniteQueryOptions` from `keepPages`: whether `load` keeps the cached pages. */
|
|
59
71
|
readonly "~keep"?: (data: never) => boolean;
|
|
60
72
|
/** Phantom: the root the builder is bound to. Never set at runtime. */
|
|
@@ -91,17 +103,18 @@ type Awaitable<T> = PromiseLike<T> | T;
|
|
|
91
103
|
*/
|
|
92
104
|
export type FromQueryFn<T> = T extends unknown ? T : never;
|
|
93
105
|
/**
|
|
94
|
-
* `queryOptions
|
|
106
|
+
* `queryOptions` for a root: `TTypes` is what the factories it builds need
|
|
107
|
+
* of a client, and `TSets` the options they can set.
|
|
95
108
|
*
|
|
96
|
-
* @see https://raf-query.katt.dev/docs/links-and-features#typing-
|
|
109
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
97
110
|
*/
|
|
98
|
-
export interface QueryOptionsBuilder<TTypes extends RootTypes> {
|
|
99
|
-
<const TKey extends QueryKey, TChunk, TData>(options: BaseOptions<TKey
|
|
100
|
-
readonly queryFn: (context: QueryFunctionContext<TKey>) => AsyncIterable<TChunk>;
|
|
111
|
+
export interface QueryOptionsBuilder<TTypes extends RootTypes, TSets extends RootTypes = TTypes> {
|
|
112
|
+
<const TKey extends QueryKey, TChunk, TData>(options: BaseOptions<TKey> & Partial<TSets["options"]> & {
|
|
113
|
+
readonly queryFn: (context: QueryFunctionContext<TKey, TTypes>) => AsyncIterable<TChunk>;
|
|
101
114
|
readonly stream: StreamOptions<TData, TChunk>;
|
|
102
115
|
}): QueryOptions<TKey, TData, TData, TTypes>;
|
|
103
|
-
<const TKey extends QueryKey, TQueryFnData, TData = TQueryFnData>(options: BaseOptions<TKey
|
|
104
|
-
readonly queryFn: (context: QueryFunctionContext<TKey>) => Awaitable<TQueryFnData>;
|
|
116
|
+
<const TKey extends QueryKey, TQueryFnData, TData = TQueryFnData>(options: BaseOptions<TKey> & Partial<TSets["options"]> & {
|
|
117
|
+
readonly queryFn: (context: QueryFunctionContext<TKey, TTypes>) => Awaitable<TQueryFnData>;
|
|
105
118
|
readonly select?: (data: FromQueryFn<TQueryFnData>) => TData;
|
|
106
119
|
}): QueryOptions<TKey, TQueryFnData, TData, TTypes>;
|
|
107
120
|
}
|
|
@@ -120,27 +133,36 @@ export interface QueryOptionsBuilder<TTypes extends RootTypes> {
|
|
|
120
133
|
* fold its chunks into the data. Readers get the data after the first chunk,
|
|
121
134
|
* and every later chunk updates it in place.
|
|
122
135
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
136
|
+
* It takes the core's options only, and its factories run on any client.
|
|
137
|
+
* For the options and the `queryFn` context a client's parts declare, use
|
|
138
|
+
* the builder {@link bindQueryOptions} returns.
|
|
125
139
|
*
|
|
126
140
|
* @see https://raf-query.katt.dev/docs/query-factories
|
|
127
141
|
*/
|
|
128
|
-
export declare const queryOptions: QueryOptionsBuilder<
|
|
142
|
+
export declare const queryOptions: QueryOptionsBuilder<NoParts>;
|
|
129
143
|
/**
|
|
130
|
-
* `queryOptions` bound to a root:
|
|
131
|
-
*
|
|
132
|
-
* client's type, or the type of a
|
|
144
|
+
* `queryOptions` bound to a root: it takes the options the root's parts
|
|
145
|
+
* declare, its `queryFn`s get their context, and its factories run on the
|
|
146
|
+
* clients that have those parts. `T` is the client's type, or the type of a
|
|
147
|
+
* function that makes it. Bind once per client:
|
|
133
148
|
*
|
|
134
149
|
* ```ts
|
|
135
150
|
* // raf.ts
|
|
136
151
|
* export const queryOptions = bindQueryOptions<typeof makeQueryClient>();
|
|
137
152
|
* ```
|
|
138
153
|
*
|
|
154
|
+
* A library names the parts its factories need by their declarations, and
|
|
155
|
+
* as `Optional` the ones whose options it sets where the client has them:
|
|
156
|
+
*
|
|
157
|
+
* ```ts
|
|
158
|
+
* const queryOptions = bindQueryOptions<Convex & Optional<Retry>>();
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
139
161
|
* It returns `queryOptions` itself; only the types change.
|
|
140
162
|
*
|
|
141
|
-
* @see https://raf-query.katt.dev/docs/links-and-features#typing-
|
|
163
|
+
* @see https://raf-query.katt.dev/docs/links-and-features#typing-options-by-the-client
|
|
142
164
|
*/
|
|
143
|
-
export declare function bindQueryOptions<T>(): QueryOptionsBuilder<RootOf<T>>;
|
|
165
|
+
export declare function bindQueryOptions<T>(): QueryOptionsBuilder<RootOf<T>, SetsOf<T>>;
|
|
144
166
|
/**
|
|
145
167
|
* A function of the query's input that returns its options. The input is a
|
|
146
168
|
* method parameter typed `unknown`, which TypeScript checks bivariantly:
|
|
@@ -198,8 +220,8 @@ export type InputOf<TFactory extends QueryFactory> = Parameters<TFactory> extend
|
|
|
198
220
|
export type InputArgs<TFactory extends QueryFactory> = Parameters<TFactory> extends [] ? [] : Parameters<TFactory> extends [infer TInput, ...Array<unknown>] ? [input: TInput] : [input?: Parameters<TFactory>[0]];
|
|
199
221
|
/** A factory's key type, the way handles carry it. */
|
|
200
222
|
export type KeyOf<TFactory extends QueryFactory> = ReturnType<TFactory>["queryKey"];
|
|
201
|
-
/** The root a factory's builder is bound to
|
|
223
|
+
/** The root a factory's builder is bound to: what the factory needs of a client. */
|
|
202
224
|
export type RootOfFactory<TFactory extends QueryFactory> = ReturnType<TFactory> extends {
|
|
203
225
|
readonly "~root"?: RootTag<infer TTypes>;
|
|
204
|
-
} ? TTypes
|
|
226
|
+
} ? TTypes : NoParts;
|
|
205
227
|
//#endregion
|