@raf-query/core 0.12.0 → 0.13.1

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +36 -2
  2. package/dist/client.d.mts +38 -5
  3. package/dist/client.mjs +37 -6
  4. package/dist/entry.d.mts +7 -0
  5. package/dist/entry.mjs +16 -2
  6. package/dist/features/focus-refetch/focus-refetch.d.mts +2 -0
  7. package/dist/features/focus-refetch/focus-refetch.mjs +2 -0
  8. package/dist/features/polling/polling.d.mts +5 -1
  9. package/dist/features/polling/polling.mjs +5 -1
  10. package/dist/features/reconnect-refetch/reconnect-refetch.d.mts +2 -0
  11. package/dist/features/reconnect-refetch/reconnect-refetch.mjs +2 -0
  12. package/dist/hydration/hydration.d.mts +38 -3
  13. package/dist/hydration/hydration.mjs +16 -2
  14. package/dist/index.d.mts +3 -2
  15. package/dist/index.mjs +2 -1
  16. package/dist/infinite/infinite.d.mts +37 -15
  17. package/dist/infinite/infinite.mjs +41 -8
  18. package/dist/infinite/paging.d.mts +71 -0
  19. package/dist/infinite/paging.mjs +62 -0
  20. package/dist/internal.d.mts +3 -3
  21. package/dist/internal.mjs +3 -3
  22. package/dist/keys/keys.d.mts +9 -1
  23. package/dist/keys/targets.d.mts +8 -2
  24. package/dist/links/retry/retry.d.mts +7 -0
  25. package/dist/links/retry/retry.mjs +2 -0
  26. package/dist/links/timeout/timeout.d.mts +10 -2
  27. package/dist/links/timeout/timeout.mjs +10 -2
  28. package/dist/load.d.mts +28 -3
  29. package/dist/load.mjs +26 -3
  30. package/dist/options.d.mts +79 -9
  31. package/dist/options.mjs +7 -3
  32. package/dist/presets.d.mts +7 -1
  33. package/dist/presets.mjs +2 -0
  34. package/dist/root.d.mts +5 -1
  35. package/dist/thenable.d.mts +2 -0
  36. package/dist/verbs.d.mts +56 -15
  37. package/dist/verbs.mjs +34 -6
  38. package/package.json +1 -1
@@ -3,11 +3,20 @@ import { DefaultTypes, RootOf, RootTypes } 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
6
- /** A paged query's data. */
6
+ /**
7
+ * A paged query's data.
8
+ *
9
+ * @see https://raf-query.katt.dev/docs/infinite-queries
10
+ */
7
11
  export interface InfiniteData<TPage, TParam = unknown> {
8
12
  readonly pageParams: ReadonlyArray<TParam>;
9
13
  readonly pages: ReadonlyArray<TPage>;
10
14
  }
15
+ /**
16
+ * What a paged `queryFn` gets: the query function context, plus the page param and the direction it loads in.
17
+ *
18
+ * @see https://raf-query.katt.dev/docs/infinite-queries
19
+ */
11
20
  export interface InfiniteQueryFunctionContext<TKey extends QueryKey, TParam> extends QueryFunctionContext<TKey> {
12
21
  readonly direction: "backward" | "forward";
13
22
  readonly pageParam: TParam;
@@ -17,15 +26,33 @@ interface InfiniteOptions<TKey extends QueryKey, TPage, TParam, TData, TTypes ex
17
26
  readonly getNextPageParam: PageParamFn<TPage, TParam>;
18
27
  readonly getPreviousPageParam?: PageParamFn<TPage, TParam>;
19
28
  readonly initialPageParam: TParam;
29
+ /**
30
+ * Whether the cached pages suit this input. Pages grow from the
31
+ * `initialPageParam` the entry was first loaded with; when part of the
32
+ * input picks only that start and stays out of the key (the item a list
33
+ * opens at), inputs that differ there share one entry. `load` asks
34
+ * before it uses the pages: on `false` it drops them, and the list loads
35
+ * again from this input's `initialPageParam`. Readers never drop pages.
36
+ * Default: keep them.
37
+ */
38
+ readonly keepPages?: (data: InfiniteData<TPage, TParam>) => boolean;
20
39
  /** Keep at most this many pages, dropping from the other end. */
21
40
  readonly maxPages?: number;
22
41
  readonly select?: (data: InfiniteData<TPage, TParam>) => TData;
23
42
  }
24
- /** What `infiniteQueryOptions` returns. */
43
+ /**
44
+ * What `infiniteQueryOptions` returns.
45
+ *
46
+ * @see https://raf-query.katt.dev/docs/infinite-queries
47
+ */
25
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, TTypes>, "getNextPageParam" | "getPreviousPageParam" | "initialPageParam" | "maxPages"> & {
26
49
  readonly "~run": (op: Operation) => Promise<unknown>;
27
50
  };
28
- /** `infiniteQueryOptions`, with `meta` checked against the root `TTypes`. */
51
+ /**
52
+ * `infiniteQueryOptions`, with `meta` checked against the root `TTypes`.
53
+ *
54
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
55
+ */
29
56
  export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes> {
30
57
  <const TKey extends QueryKey, TPage, TParam, TData = InfiniteData<TPage, TParam>>(options: InfiniteOptions<TKey, FromQueryFn<TPage>, TParam, TData, TTypes> & {
31
58
  readonly queryFn: (context: InfiniteQueryFunctionContext<TKey, TParam>) => PromiseLike<TPage> | TPage;
@@ -36,10 +63,10 @@ export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes> {
36
63
  * and, on their state, `fetchNextPage` and `fetchPreviousPage`:
37
64
  *
38
65
  * ```ts
39
- * export const issueList = (input: { status: Status }) =>
66
+ * export const commentsQuery = (input: { slug: string }) =>
40
67
  * infiniteQueryOptions({
41
- * queryKey: issues("list", input),
42
- * queryFn: ({ pageParam, signal }) => listIssues({ ...input, cursor: pageParam }, { signal }),
68
+ * queryKey: comments(input.slug),
69
+ * queryFn: ({ pageParam, signal }) => listComments({ ...input, cursor: pageParam }, { signal }),
43
70
  * initialPageParam: 0,
44
71
  * getNextPageParam: (lastPage) => lastPage.nextCursor,
45
72
  * });
@@ -47,6 +74,8 @@ export interface InfiniteQueryOptionsBuilder<TTypes extends RootTypes> {
47
74
  *
48
75
  * Its `meta` is any record. To check `meta` against a client's links and
49
76
  * features, use the builder {@link bindInfiniteQueryOptions} returns.
77
+ *
78
+ * @see https://raf-query.katt.dev/docs/infinite-queries
50
79
  */
51
80
  export declare const infiniteQueryOptions: InfiniteQueryOptionsBuilder<DefaultTypes>;
52
81
  /**
@@ -57,15 +86,8 @@ export declare const infiniteQueryOptions: InfiniteQueryOptionsBuilder<DefaultTy
57
86
  * // raf.ts
58
87
  * export const infiniteQueryOptions = bindInfiniteQueryOptions<typeof makeQueryClient>();
59
88
  * ```
89
+ *
90
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
60
91
  */
61
92
  export declare function bindInfiniteQueryOptions<T>(): InfiniteQueryOptionsBuilder<RootOf<T>>;
62
- interface PagedSource {
63
- readonly getNextPageParam: PageParamFn<unknown, unknown>;
64
- readonly getPreviousPageParam?: PageParamFn<unknown, unknown>;
65
- readonly initialPageParam: unknown;
66
- readonly maxPages?: number;
67
- readonly queryFn: (context: InfiniteQueryFunctionContext<QueryKey, unknown>) => unknown;
68
- }
69
- /** The param of the page after (or before) `data`, or `undefined` at the end. */
70
- export declare function pageParamAfter(options: Pick<PagedSource, "getNextPageParam" | "getPreviousPageParam">, data: InfiniteData<unknown>, direction: "next" | "previous"): unknown;
71
93
  //#endregion
@@ -1,13 +1,14 @@
1
+ import { hashKey } from "../keys/keys.mjs";
1
2
  //#region src/infinite/infinite.ts
2
3
  /**
3
4
  * Typed options for a paged query factory. Readers get `{ pages, pageParams }`
4
5
  * and, on their state, `fetchNextPage` and `fetchPreviousPage`:
5
6
  *
6
7
  * ```ts
7
- * export const issueList = (input: { status: Status }) =>
8
+ * export const commentsQuery = (input: { slug: string }) =>
8
9
  * infiniteQueryOptions({
9
- * queryKey: issues("list", input),
10
- * queryFn: ({ pageParam, signal }) => listIssues({ ...input, cursor: pageParam }, { signal }),
10
+ * queryKey: comments(input.slug),
11
+ * queryFn: ({ pageParam, signal }) => listComments({ ...input, cursor: pageParam }, { signal }),
11
12
  * initialPageParam: 0,
12
13
  * getNextPageParam: (lastPage) => lastPage.nextCursor,
13
14
  * });
@@ -15,9 +16,12 @@
15
16
  *
16
17
  * Its `meta` is any record. To check `meta` against a client's links and
17
18
  * features, use the builder {@link bindInfiniteQueryOptions} returns.
19
+ *
20
+ * @see https://raf-query.katt.dev/docs/infinite-queries
18
21
  */
19
22
  const infiniteQueryOptions = (options) => ({
20
23
  ...options,
24
+ "~keep": options.keepPages,
21
25
  "~run": (op) => runPages(op, options)
22
26
  });
23
27
  /**
@@ -28,6 +32,8 @@ const infiniteQueryOptions = (options) => ({
28
32
  * // raf.ts
29
33
  * export const infiniteQueryOptions = bindInfiniteQueryOptions<typeof makeQueryClient>();
30
34
  * ```
35
+ *
36
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
31
37
  */
32
38
  function bindInfiniteQueryOptions() {
33
39
  return infiniteQueryOptions;
@@ -41,8 +47,25 @@ function pageParamAfter(options, data, direction) {
41
47
  if (page === void 0 || !getParam) return;
42
48
  return getParam(page, data.pages, data.pageParams[index]) ?? void 0;
43
49
  }
50
+ /**
51
+ * The entry's data as it is now, which writes may have changed since `op`
52
+ * started, or `fallback` while it has none.
53
+ */
54
+ function latest(op, fallback) {
55
+ const state = op.client["~entries"].get(op.hash)?.state;
56
+ return state?.hasData ? state.data : fallback;
57
+ }
58
+ function sameParam(a, b) {
59
+ return hashKey([a]) === hashKey([b]);
60
+ }
61
+ /** The page `data` holds for `pageParam`, if any. */
62
+ function pageFor(data, pageParam) {
63
+ const index = data?.pageParams.findIndex((param) => sameParam(param, pageParam)) ?? -1;
64
+ return index === -1 ? void 0 : data?.pages[index];
65
+ }
44
66
  async function runPages(op, source) {
45
67
  const fetchPage = (pageParam, direction) => Promise.resolve(source.queryFn({
68
+ client: op.client,
46
69
  direction,
47
70
  meta: op.meta,
48
71
  pageParam,
@@ -55,20 +78,26 @@ async function runPages(op, source) {
55
78
  const pageParam = pageParamAfter(source, previous, direction);
56
79
  if (pageParam === void 0) return previous;
57
80
  const page = await fetchPage(pageParam, direction === "next" ? "forward" : "backward");
81
+ const current = latest(op, previous);
82
+ const edge = (data) => direction === "next" ? data.pageParams.at(-1) : data.pageParams[0];
83
+ if (!sameParam(edge(current), edge(previous))) return current;
58
84
  const max = source.maxPages ?? Infinity;
59
85
  return direction === "next" ? {
60
- pageParams: [...previous.pageParams, pageParam].slice(-max),
61
- pages: [...previous.pages, page].slice(-max)
86
+ pageParams: [...current.pageParams, pageParam].slice(-max),
87
+ pages: [...current.pages, page].slice(-max)
62
88
  } : {
63
- pageParams: [pageParam, ...previous.pageParams].slice(0, max),
64
- pages: [page, ...previous.pages].slice(0, max)
89
+ pageParams: [pageParam, ...current.pageParams].slice(0, max),
90
+ pages: [page, ...current.pages].slice(0, max)
65
91
  };
66
92
  }
67
93
  const count = previous?.pages.length ?? op.pages ?? 1;
68
94
  const pages = [];
69
95
  const pageParams = [];
96
+ /** The page the entry held for each param when that page's read started. */
97
+ const before = [];
70
98
  let pageParam = previous?.pageParams[0] ?? source.initialPageParam;
71
99
  while (pages.length < count) {
100
+ before.push(pageFor(latest(op, void 0), pageParam));
72
101
  const page = await fetchPage(pageParam, "forward");
73
102
  pages.push(page);
74
103
  pageParams.push(pageParam);
@@ -79,9 +108,13 @@ async function runPages(op, source) {
79
108
  if (next === void 0) break;
80
109
  pageParam = next;
81
110
  }
111
+ const now = latest(op, void 0);
82
112
  return {
83
113
  pageParams,
84
- pages
114
+ pages: pages.map((page, index) => {
115
+ const written = pageFor(now, pageParams[index]);
116
+ return written !== void 0 && written !== before[index] ? written : page;
117
+ })
85
118
  };
86
119
  }
87
120
  //#endregion
@@ -0,0 +1,71 @@
1
+ import { InfiniteQueryFactory, InputArgs } from "../options.mjs";
2
+ import { Entry, EntryState } from "../entry.mjs";
3
+ import { ClientFor } from "../verbs.mjs";
4
+ //#region src/infinite/paging.d.ts
5
+ /**
6
+ * Which way a page loads: after the last one, or before the first.
7
+ *
8
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
9
+ */
10
+ export type PageDirection = "next" | "previous";
11
+ /**
12
+ * Where a paged query can load more, and what it's loading now.
13
+ *
14
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
15
+ */
16
+ export interface PageState {
17
+ readonly hasNextPage: boolean;
18
+ readonly hasPreviousPage: boolean;
19
+ readonly isFetchingNextPage: boolean;
20
+ readonly isFetchingPreviousPage: boolean;
21
+ }
22
+ /**
23
+ * A paged query's {@link PageState} and the requests that load more:
24
+ * `useInfiniteQuery`'s paging controls.
25
+ *
26
+ * @see https://raf-query.katt.dev/docs/infinite-queries#reading-pages
27
+ */
28
+ export interface PageControls extends PageState {
29
+ /** Load the page after the last one. Resolves when it's there. */
30
+ fetchNextPage(): Promise<void>;
31
+ /** Load the page before the first one. Resolves when it's there. */
32
+ fetchPreviousPage(): Promise<void>;
33
+ }
34
+ /** A paged entry's {@link PageState}, from `state` (the entry's own by default). */
35
+ export declare function pageState(entry: Entry, state?: EntryState): PageState;
36
+ /**
37
+ * Load a paged entry's page in `direction`; resolves when the request
38
+ * settles, and does nothing without a page at that end. An error stays in
39
+ * the entry's state.
40
+ */
41
+ export declare function fetchPage(entry: Entry, direction: PageDirection): Promise<void>;
42
+ /**
43
+ * Load the page after the last one of a paged query, as `useInfiniteQuery`'s
44
+ * `fetchNextPage()` does. Resolves when the page is there, or the request
45
+ * settles; does nothing without a next page.
46
+ *
47
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
48
+ */
49
+ export declare function fetchNextPage<TFactory extends InfiniteQueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): Promise<void>;
50
+ /**
51
+ * Load the page before the first one of a paged query, as
52
+ * `useInfiniteQuery`'s `fetchPreviousPage()` does. See {@link fetchNextPage}.
53
+ *
54
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
55
+ */
56
+ export declare function fetchPreviousPage<TFactory extends InfiniteQueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): Promise<void>;
57
+ /**
58
+ * Whether a paged query has a page after its last one: `false` while it has
59
+ * no data, or once `getNextPageParam` returns `undefined`.
60
+ *
61
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
62
+ */
63
+ export declare function hasNextPage<TFactory extends InfiniteQueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): boolean;
64
+ /**
65
+ * Whether a paged query has a page before its first one. See
66
+ * {@link hasNextPage}.
67
+ *
68
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
69
+ */
70
+ export declare function hasPreviousPage<TFactory extends InfiniteQueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): boolean;
71
+ //#endregion
@@ -0,0 +1,62 @@
1
+ import { entryOf, fetchEntry } from "../entry.mjs";
2
+ import { pageParamAfter } from "./infinite.mjs";
3
+ //#region src/infinite/paging.ts
4
+ function hasPage(entry, state, direction) {
5
+ return state.hasData && pageParamAfter(entry.options, state.data, direction) !== void 0;
6
+ }
7
+ /** A paged entry's {@link PageState}, from `state` (the entry's own by default). */
8
+ function pageState(entry, state = entry.state) {
9
+ return {
10
+ hasNextPage: hasPage(entry, state, "next"),
11
+ hasPreviousPage: hasPage(entry, state, "previous"),
12
+ isFetchingNextPage: state.fetchingDirection === "next",
13
+ isFetchingPreviousPage: state.fetchingDirection === "previous"
14
+ };
15
+ }
16
+ /**
17
+ * Load a paged entry's page in `direction`; resolves when the request
18
+ * settles, and does nothing without a page at that end. An error stays in
19
+ * the entry's state.
20
+ */
21
+ function fetchPage(entry, direction) {
22
+ return fetchEntry(entry, { direction }).then(() => {});
23
+ }
24
+ /**
25
+ * Load the page after the last one of a paged query, as `useInfiniteQuery`'s
26
+ * `fetchNextPage()` does. Resolves when the page is there, or the request
27
+ * settles; does nothing without a next page.
28
+ *
29
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
30
+ */
31
+ function fetchNextPage(client, factory, ...input) {
32
+ return fetchPage(entryOf(client, factory, input[0]), "next");
33
+ }
34
+ /**
35
+ * Load the page before the first one of a paged query, as
36
+ * `useInfiniteQuery`'s `fetchPreviousPage()` does. See {@link fetchNextPage}.
37
+ *
38
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
39
+ */
40
+ function fetchPreviousPage(client, factory, ...input) {
41
+ return fetchPage(entryOf(client, factory, input[0]), "previous");
42
+ }
43
+ /**
44
+ * Whether a paged query has a page after its last one: `false` while it has
45
+ * no data, or once `getNextPageParam` returns `undefined`.
46
+ *
47
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
48
+ */
49
+ function hasNextPage(client, factory, ...input) {
50
+ return pageState(entryOf(client, factory, input[0])).hasNextPage;
51
+ }
52
+ /**
53
+ * Whether a paged query has a page before its first one. See
54
+ * {@link hasNextPage}.
55
+ *
56
+ * @see https://raf-query.katt.dev/docs/infinite-queries#outside-react
57
+ */
58
+ function hasPreviousPage(client, factory, ...input) {
59
+ return pageState(entryOf(client, factory, input[0])).hasPreviousPage;
60
+ }
61
+ //#endregion
62
+ export { fetchNextPage, fetchPage, fetchPreviousPage, hasNextPage, hasPreviousPage, pageState };
@@ -2,12 +2,12 @@ import { AnyFactory, hashKey } from "./keys/keys.mjs";
2
2
  import { Decl, DefaultTypes, MetaOf, RootOf, RootTypes } from "./root.mjs";
3
3
  import { AnyTarget } from "./keys/targets.mjs";
4
4
  import { fulfilled, mapThenable, pending, rejected } from "./thenable.mjs";
5
- import { Entry, EntryState, entryOf, fetchEntry, isInvalidated, isStale, remove, reset, subscribeEntry } from "./entry.mjs";
5
+ import { Entry, EntryState, entryOf, fetchEntry, isBrowserOnly, isInvalidated, isStale, remove, reset, subscribeEntry } from "./entry.mjs";
6
6
  import { AnyFeature, AnyLink, ClientEvent, mount, systemClock } from "./client.mjs";
7
7
  import { FocusRefetchMeta } from "./features/focus-refetch/focus-refetch.mjs";
8
8
  import { ReconnectRefetchMeta } from "./features/reconnect-refetch/reconnect-refetch.mjs";
9
9
  import { PollingMeta } from "./features/polling/polling.mjs";
10
- import { pageParamAfter } from "./infinite/infinite.mjs";
10
+ import { fetchPage, pageState } from "./infinite/paging.mjs";
11
11
  import { RetryMeta } from "./links/retry/retry.mjs";
12
12
  import { LoadRecord, isWaterfallHandle, loadsOf, readData, startIfStale } from "./load.mjs";
13
- export { type AnyFactory, type AnyFeature, type AnyLink, type AnyTarget, type ClientEvent, type Decl, type DefaultTypes, type Entry, type EntryState, type FocusRefetchMeta, type LoadRecord, type MetaOf, type PollingMeta, type ReconnectRefetchMeta, type RetryMeta, type RootOf, type RootTypes, entryOf, fetchEntry, fulfilled, hashKey, isInvalidated, isStale, isWaterfallHandle, loadsOf, mapThenable, mount, pageParamAfter, pending, readData, rejected, remove, reset, startIfStale, subscribeEntry, systemClock };
13
+ export { type AnyFactory, type AnyFeature, type AnyLink, type AnyTarget, type ClientEvent, type Decl, type DefaultTypes, type Entry, type EntryState, type FocusRefetchMeta, type LoadRecord, type MetaOf, type PollingMeta, type ReconnectRefetchMeta, type RetryMeta, type RootOf, type RootTypes, entryOf, fetchEntry, fetchPage, fulfilled, hashKey, isBrowserOnly, isInvalidated, isStale, isWaterfallHandle, loadsOf, mapThenable, mount, pageState, pending, readData, rejected, remove, reset, startIfStale, subscribeEntry, systemClock };
package/dist/internal.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { mount, systemClock } from "./client.mjs";
2
2
  import { hashKey } from "./keys/keys.mjs";
3
3
  import { fulfilled, mapThenable, pending, rejected } from "./thenable.mjs";
4
- import { entryOf, fetchEntry, isInvalidated, isStale, remove, reset, subscribeEntry } from "./entry.mjs";
5
- import { pageParamAfter } from "./infinite/infinite.mjs";
4
+ import { entryOf, fetchEntry, isBrowserOnly, isInvalidated, isStale, remove, reset, subscribeEntry } from "./entry.mjs";
5
+ import { fetchPage, pageState } from "./infinite/paging.mjs";
6
6
  import { isWaterfallHandle, loadsOf, readData, startIfStale } from "./load.mjs";
7
- export { entryOf, fetchEntry, fulfilled, hashKey, isInvalidated, isStale, isWaterfallHandle, loadsOf, mapThenable, mount, pageParamAfter, pending, readData, rejected, remove, reset, startIfStale, subscribeEntry, systemClock };
7
+ export { entryOf, fetchEntry, fetchPage, fulfilled, hashKey, isBrowserOnly, isInvalidated, isStale, isWaterfallHandle, loadsOf, mapThenable, mount, pageState, pending, readData, rejected, remove, reset, startIfStale, subscribeEntry, systemClock };
@@ -8,13 +8,19 @@
8
8
  * that builds or matches a key lives in this folder, so the shape of
9
9
  * grouping can change without touching the cache.
10
10
  */
11
- /** A query's key: a plain, serializable array. */
11
+ /**
12
+ * A query's key: a plain, serializable array.
13
+ *
14
+ * @see https://raf-query.katt.dev/docs/query-keys
15
+ */
12
16
  export type QueryKey = ReadonlyArray<unknown>;
13
17
  declare const groupBrand: unique symbol;
14
18
  /**
15
19
  * A named set of queries: those whose key starts with its path. Call it
16
20
  * for a key under that path; a subgroup's path extends its parent's, so a
17
21
  * group covers its subgroups and their queries.
22
+ *
23
+ * @see https://raf-query.katt.dev/docs/query-keys#groups
18
24
  */
19
25
  export interface Group<TPath extends ReadonlyArray<string> = ReadonlyArray<string>> {
20
26
  <const TRest extends QueryKey>(...rest: TRest): readonly [...TPath, ...TRest];
@@ -34,6 +40,8 @@ export interface Group<TPath extends ReadonlyArray<string> = ReadonlyArray<strin
34
40
  * queryOptions({ queryKey: drafts("byId", input), queryFn }); // ["posts", "drafts", "byId", input]
35
41
  * await invalidateMany(client, posts); // drafts too
36
42
  * ```
43
+ *
44
+ * @see https://raf-query.katt.dev/docs/query-keys#groups
37
45
  */
38
46
  export declare function group<const TName extends string>(name: TName): Group<readonly [TName]>;
39
47
  export declare function group<const TPath extends ReadonlyArray<string>, const TName extends string>(parent: Group<TPath>, name: TName): Group<readonly [...TPath, TName]>;
@@ -1,7 +1,11 @@
1
1
  import { AnyFactory, Group, QueryKey } from "./keys.mjs";
2
2
  import { QueryMeta } from "../root.mjs";
3
3
  //#region src/keys/targets.d.ts
4
- /** What a target's `where` sees of a query. */
4
+ /**
5
+ * What a target's `where` sees of a query.
6
+ *
7
+ * @see https://raf-query.katt.dev/docs/query-invalidation#matching-with-where
8
+ */
5
9
  export interface QueryInfo<TMeta = QueryMeta> {
6
10
  /** The query's data, before `select`; `undefined` without data. */
7
11
  readonly data: unknown;
@@ -16,8 +20,10 @@ export interface QueryInfo<TMeta = QueryMeta> {
16
20
  *
17
21
  * ```ts
18
22
  * const ownedBy: Target<AppMeta, Team> = { where: (query, team) => query.meta.owner === team };
19
- * await invalidateMany(client, ownedBy, "posts-team");
23
+ * await invalidateMany(client, ownedBy, "editorial");
20
24
  * ```
25
+ *
26
+ * @see https://raf-query.katt.dev/docs/query-invalidation#targets
21
27
  */
22
28
  export interface Target<TMeta = QueryMeta, TParam = never> {
23
29
  readonly where: (query: QueryInfo<TMeta>, param: TParam) => boolean;
@@ -1,5 +1,10 @@
1
1
  import { Link } from "../../client.mjs";
2
2
  //#region src/links/retry/retry.d.ts
3
+ /**
4
+ * Options for {@link retry}.
5
+ *
6
+ * @see https://raf-query.katt.dev/docs/retries#options
7
+ */
3
8
  export interface RetryOptions {
4
9
  /** Retries after the first attempt. A query's `meta.retry` wins. Default 3. */
5
10
  readonly attempts?: number;
@@ -19,6 +24,8 @@ export interface RetryMeta {
19
24
  * server clients never retry, and a browser that is offline
20
25
  * waits until it's back online before retrying. A query sets its own
21
26
  * attempts with `meta: { retry }`.
27
+ *
28
+ * @see https://raf-query.katt.dev/docs/retries
22
29
  */
23
30
  export declare function retry(options?: RetryOptions): Link<{
24
31
  readonly meta: RetryMeta;
@@ -32,6 +32,8 @@ const notThrownResponse = (error) => !isResponse(error);
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
34
  * attempts with `meta: { retry }`.
35
+ *
36
+ * @see https://raf-query.katt.dev/docs/retries
35
37
  */
36
38
  function retry(options = {}) {
37
39
  return link(async (op, next) => {
@@ -1,9 +1,17 @@
1
1
  import { Link } from "../../client.mjs";
2
2
  //#region src/links/timeout/timeout.d.ts
3
- /** What a request that took too long fails with. */
3
+ /**
4
+ * What a request that took too long fails with.
5
+ *
6
+ * @see https://raf-query.katt.dev/docs/retries#timeouts
7
+ */
4
8
  export declare class QueryTimeoutError extends Error {
5
9
  readonly name = "QueryTimeoutError";
6
10
  }
7
- /** Fail a request (and abort its `signal`) when it takes longer than `ms`. */
11
+ /**
12
+ * Fail a request (and abort its `signal`) when it takes longer than `ms`.
13
+ *
14
+ * @see https://raf-query.katt.dev/docs/retries#timeouts
15
+ */
8
16
  export declare function timeout(ms: number): Link;
9
17
  //#endregion
@@ -1,9 +1,17 @@
1
1
  //#region src/links/timeout/timeout.ts
2
- /** What a request that took too long fails with. */
2
+ /**
3
+ * What a request that took too long fails with.
4
+ *
5
+ * @see https://raf-query.katt.dev/docs/retries#timeouts
6
+ */
3
7
  var QueryTimeoutError = class extends Error {
4
8
  name = "QueryTimeoutError";
5
9
  };
6
- /** Fail a request (and abort its `signal`) when it takes longer than `ms`. */
10
+ /**
11
+ * Fail a request (and abort its `signal`) when it takes longer than `ms`.
12
+ *
13
+ * @see https://raf-query.katt.dev/docs/retries#timeouts
14
+ */
7
15
  function timeout(ms) {
8
16
  return (op, next) => {
9
17
  const controller = new AbortController();
package/dist/load.d.mts CHANGED
@@ -6,13 +6,19 @@ import { QueryClient } from "./client.mjs";
6
6
  * A small serializable reference to a query: its key and its factory's
7
7
  * input. It carries no data; readers get that from the cache. Handles of
8
8
  * different factories have different types.
9
+ *
10
+ * @see https://raf-query.katt.dev/docs/reading-queries#handles
9
11
  */
10
12
  export interface QueryHandle<TFactory extends QueryFactory = QueryFactory> {
11
13
  readonly input: InputOf<TFactory>;
12
14
  readonly queryKey: KeyOf<TFactory>;
13
15
  }
14
16
  type LoadKind = "prefetch" | "revalidate" | "swr";
15
- /** A query for `load` to start. Building one starts nothing. */
17
+ /**
18
+ * A query for `load` to start. Building one starts nothing.
19
+ *
20
+ * @see https://raf-query.katt.dev/docs/starting-queries
21
+ */
16
22
  export interface LoadEntry<TFactory extends QueryFactory = QueryFactory, TKind extends LoadKind = LoadKind> {
17
23
  readonly factory: TFactory;
18
24
  readonly input: InputOf<TFactory>;
@@ -20,6 +26,11 @@ export interface LoadEntry<TFactory extends QueryFactory = QueryFactory, TKind e
20
26
  /** For paged factories: how many pages a first load fetches. */
21
27
  readonly pages?: number;
22
28
  }
29
+ /**
30
+ * Options for a `load` entry.
31
+ *
32
+ * @see https://raf-query.katt.dev/docs/infinite-queries#loading-several-pages-up-front
33
+ */
23
34
  export interface LoadEntryOptions {
24
35
  /** For paged factories: how many pages a first load fetches. Default 1. */
25
36
  readonly pages?: number;
@@ -29,6 +40,8 @@ type LoadEntryArgs<TFactory extends QueryFactory> = [input: InputOf<TFactory>, o
29
40
  * Start the query if the cache has no fresh data, and don't wait for it.
30
41
  * It never makes the load reject: errors show up where a component reads
31
42
  * the handle.
43
+ *
44
+ * @see https://raf-query.katt.dev/docs/starting-queries#prefetch-or-swr
32
45
  */
33
46
  export declare function prefetch<TFactory extends QueryFactory>(factory: TFactory, ...args: LoadEntryArgs<TFactory>): LoadEntry<TFactory, "prefetch">;
34
47
  /**
@@ -37,6 +50,8 @@ export declare function prefetch<TFactory extends QueryFactory>(factory: TFactor
37
50
  * HTTP's
38
51
  * [`stale-while-revalidate`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control#stale-while-revalidate)
39
52
  * does. The load rejects if the fetch it waits for fails.
53
+ *
54
+ * @see https://raf-query.katt.dev/docs/starting-queries#prefetch-or-swr
40
55
  */
41
56
  export declare function swr<TFactory extends QueryFactory>(factory: TFactory, ...args: LoadEntryArgs<TFactory>): LoadEntry<TFactory, "swr">;
42
57
  /**
@@ -46,6 +61,8 @@ export declare function swr<TFactory extends QueryFactory>(factory: TFactory, ..
46
61
  * is the max-age); with stale data or none it waits for the fetch. On a
47
62
  * server client, data counts as fresh until a write invalidates it. The
48
63
  * load rejects if the fetch fails.
64
+ *
65
+ * @see https://raf-query.katt.dev/docs/starting-queries#the-three-entries
49
66
  */
50
67
  export declare function revalidate<TFactory extends QueryFactory>(factory: TFactory, ...args: LoadEntryArgs<TFactory>): LoadEntry<TFactory, "revalidate">;
51
68
  /**
@@ -58,6 +75,8 @@ export declare function revalidate<TFactory extends QueryFactory>(factory: TFact
58
75
  * drafts: user.isAdmin ? prefetch(draftsQuery, { slug }) : skipToken,
59
76
  * });
60
77
  * ```
78
+ *
79
+ * @see https://raf-query.katt.dev/docs/starting-queries#conditional-queries
61
80
  */
62
81
  export declare const skipToken: unique symbol;
63
82
  /** What `load` takes per name: an entry, or `skipToken`. */
@@ -68,6 +87,8 @@ type LoadedData<TEntries extends LoadEntries> = { [TName in keyof TEntries as TE
68
87
  /**
69
88
  * What `load` resolves to: a handle per entry (`undefined` for `skipToken`),
70
89
  * and the data of `swr` and `revalidate` entries.
90
+ *
91
+ * @see https://raf-query.katt.dev/docs/starting-queries
71
92
  */
72
93
  export type Loaded<TEntries extends LoadEntries> = readonly [handles: { [TName in keyof TEntries]: HandleOf<TEntries[TName]>; }, data: LoadedData<TEntries>];
73
94
  /** A `load` call as devtools show it. */
@@ -96,10 +117,12 @@ export declare function startIfStale(entry: Entry): void;
96
117
  *
97
118
  * ```ts
98
119
  * const [handles, data] = await load(queryClient, {
99
- * comments: prefetch(commentsQuery, { issueId: id }),
100
- * issue: swr(issueQuery, { id }),
120
+ * comments: prefetch(commentsQuery, { slug }),
121
+ * post: swr(postQuery, { slug }),
101
122
  * });
102
123
  * ```
124
+ *
125
+ * @see https://raf-query.katt.dev/docs/starting-queries
103
126
  */
104
127
  export declare function load<const TEntries extends LoadEntries>(client: QueryClient, entries: TEntries): Promise<Loaded<TEntries>>;
105
128
  /** Whether a handle came from `waterfallHandle()`: reading it is expected to fetch. */
@@ -118,6 +141,8 @@ export declare function isWaterfallHandle(handle: Pick<QueryHandle, "queryKey">)
118
141
  * ```ts
119
142
  * const searchHandle = waterfallHandle(searchQuery, props.search, (input) => ({ ...input, q }));
120
143
  * ```
144
+ *
145
+ * @see https://raf-query.katt.dev/docs/request-waterfalls#render-time-inputs-waterfallhandle
121
146
  */
122
147
  export declare function waterfallHandle<TFactory extends QueryFactory>(factory: TFactory, ...input: InputArgs<TFactory>): QueryHandle<TFactory>;
123
148
  export declare function waterfallHandle<TFactory extends QueryFactory>(factory: TFactory, handle: QueryHandle<TFactory>, update: (input: InputOf<TFactory>) => InputOf<TFactory>): QueryHandle<TFactory>;