@raf-query/react 0.9.2 → 0.10.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.
- package/CHANGELOG.md +27 -1
- package/README.md +5 -7
- package/dist/devtools-panel.d.mts +1 -1
- package/dist/devtools-panel.mjs +1 -1
- package/dist/{hydrate.mjs → hydration-boundary/hydrate.mjs} +3 -4
- package/dist/hydration-boundary/hydration-boundary-react-server.d.mts +11 -0
- package/dist/hydration-boundary/hydration-boundary-react-server.mjs +30 -0
- package/dist/hydration-boundary/hydration-boundary.d.mts +64 -0
- package/dist/{react-router.mjs → hydration-boundary/hydration-boundary.mjs} +22 -4
- package/dist/{sent.mjs → hydration-boundary/sent.mjs} +1 -1
- package/dist/index-react-server.d.mts +9 -0
- package/dist/index-react-server.mjs +8 -0
- package/dist/index-shared.d.mts +7 -0
- package/dist/index-shared.mjs +7 -0
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +3 -3
- package/dist/provider.d.mts +1 -1
- package/dist/{browser-requests.mjs → query-provider/browser-requests.mjs} +1 -1
- package/dist/{query-provider.d.mts → query-provider/query-provider.d.mts} +2 -2
- package/dist/{query-provider.mjs → query-provider/query-provider.mjs} +3 -3
- package/dist/tanstack-router-shared.d.mts +1 -2
- package/dist/tanstack-router-shared.mjs +1 -1
- package/dist/use-query.d.mts +1 -62
- package/dist/use-query.mjs +4 -45
- package/dist/use-waterfall.d.mts +1 -1
- package/dist/use-waterfall.mjs +2 -2
- package/package.json +6 -5
- package/dist/all-keyed.d.mts +0 -18
- package/dist/all-keyed.mjs +0 -19
- package/dist/client.d.mts +0 -124
- package/dist/client.mjs +0 -176
- package/dist/react-router.d.mts +0 -35
- package/dist/rsc.d.mts +0 -28
- package/dist/rsc.mjs +0 -34
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.10.1](https://github.com/KATT/raf-query/compare/0.10.0...0.10.1) (2026-10-16)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* **core:** export QueryClient, dehydrate, hydrate, allKeyed and the useQuery controls from @raf-query/core ([#193](https://github.com/KATT/raf-query/issues/193)) ([54492ab](https://github.com/KATT/raf-query/commit/54492abbe2966a0645e8a4c77f9c5ab31d6e3a20)), references [#194](https://github.com/KATT/raf-query/issues/194)
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
* React Router client-only and server sections with one server client per request, Effect under Integrations, official docs links, and ensure waits like fetch in server-only code ([#192](https://github.com/KATT/raf-query/issues/192)) ([841ffcf](https://github.com/KATT/raf-query/commit/841ffcf4d0fa0a40dfc58dc65bfcfadca8948874)), references [#190](https://github.com/KATT/raf-query/issues/190)
|
|
12
|
+
|
|
13
|
+
## [0.10.0](https://github.com/KATT/raf-query/compare/0.9.2...0.10.0) (2026-10-16)
|
|
14
|
+
|
|
15
|
+
### ⚠ BREAKING CHANGES
|
|
16
|
+
|
|
17
|
+
- **react:** import HydrationBoundary from @raf-query/react in RSC and React Router ([#175](https://github.com/KATT/raf-query/issues/175))
|
|
18
|
+
- **react:** import QueryProvider from @raf-query/react ([#177](https://github.com/KATT/raf-query/issues/177))
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
- **react:** import HydrationBoundary from @raf-query/react in RSC and React Router ([#175](https://github.com/KATT/raf-query/issues/175)) ([244705c](https://github.com/KATT/raf-query/commit/244705c74841d280a596195dec5cf5e5d5617fe5))
|
|
23
|
+
- **react:** import QueryProvider from @raf-query/react ([#177](https://github.com/KATT/raf-query/issues/177)) ([fb4fceb](https://github.com/KATT/raf-query/commit/fb4fcebb404906b4a9d5716a1d45cb33c82da2fb)), references [#175](https://github.com/KATT/raf-query/issues/175) [#175](https://github.com/KATT/raf-query/issues/175) [#175](https://github.com/KATT/raf-query/issues/175) [#175](https://github.com/KATT/raf-query/issues/175)
|
|
24
|
+
|
|
25
|
+
### Code Refactoring
|
|
26
|
+
|
|
27
|
+
- **react:** group the HydrationBoundary and QueryProvider files in folders ([#186](https://github.com/KATT/raf-query/issues/186)) ([ad07bb4](https://github.com/KATT/raf-query/commit/ad07bb45ca77fc797cd6b8432685e58f43907258)), references [#175](https://github.com/KATT/raf-query/issues/175)
|
|
28
|
+
|
|
3
29
|
## [0.9.2](https://github.com/KATT/raf-query/compare/0.9.1...0.9.2) (2026-10-15)
|
|
4
30
|
|
|
5
31
|
### Bug Fixes
|
|
6
32
|
|
|
7
|
-
|
|
33
|
+
- **core:** keep handles of factories with the same signature apart ([#167](https://github.com/KATT/raf-query/issues/167)) ([5894bcb](https://github.com/KATT/raf-query/commit/5894bcbcc382c60e9c04768c0e178bf0996f4b45))
|
|
8
34
|
|
|
9
35
|
## [0.9.1](https://github.com/KATT/raf-query/compare/0.9.0...0.9.1) (2026-10-15)
|
|
10
36
|
|
package/README.md
CHANGED
|
@@ -124,13 +124,11 @@ function PostPage() {
|
|
|
124
124
|
|
|
125
125
|
## Entry points
|
|
126
126
|
|
|
127
|
-
| Import | Use
|
|
128
|
-
| ---------------------------------- |
|
|
129
|
-
| `@raf-query/react` | `
|
|
130
|
-
| `@raf-query/react/tanstack-router` | [TanStack Start and Router](https://raf-query.katt.dev/docs/tanstack-start) SSR streaming
|
|
131
|
-
| `@raf-query/react/
|
|
132
|
-
| `@raf-query/react/react-router` | [React Router](https://raf-query.katt.dev/docs/react-router) Framework Mode loaders |
|
|
133
|
-
| `@raf-query/react/devtools` | The [devtools](https://raf-query.katt.dev/docs/devtools) panel; omit the element to tree-shake it |
|
|
127
|
+
| Import | Use |
|
|
128
|
+
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
129
|
+
| `@raf-query/react` | `QueryClientProvider`, `QueryProvider`, `useQuery`, `useWaterfall`, `useIsFetching`, `HydrationBoundary`, and all of core, `QueryClient` included |
|
|
130
|
+
| `@raf-query/react/tanstack-router` | [TanStack Start and Router](https://raf-query.katt.dev/docs/tanstack-start) SSR streaming |
|
|
131
|
+
| `@raf-query/react/devtools` | The [devtools](https://raf-query.katt.dev/docs/devtools) panel; omit the element to tree-shake it |
|
|
134
132
|
|
|
135
133
|
## License
|
|
136
134
|
|
package/dist/devtools-panel.mjs
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { useOptionalQueryClient } from "./provider.mjs";
|
|
3
3
|
import { countByStatus, sortOrders, statuses, useQueryRows, visibleRows } from "./devtools-store.mjs";
|
|
4
4
|
import { Query } from "@raf-query/core";
|
|
5
|
-
import { Effect, Predicate } from "effect";
|
|
6
5
|
import { useState, useSyncExternalStore } from "react";
|
|
7
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Effect, Predicate } from "effect";
|
|
8
8
|
//#region src/devtools-panel.tsx
|
|
9
9
|
const palettes = {
|
|
10
10
|
dark: {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { Query, hashKey } from "@raf-query/core";
|
|
2
|
+
import { useQueryClient } from "../provider.mjs";
|
|
3
|
+
import { Query, hashKey, hydrate } from "@raf-query/core";
|
|
5
4
|
import { useEffect, useState } from "react";
|
|
6
|
-
//#region src/hydrate.tsx
|
|
5
|
+
//#region src/hydration-boundary/hydrate.tsx
|
|
7
6
|
/**
|
|
8
7
|
* Entries the client has no data for, which children need during this
|
|
9
8
|
* render, and entries it already shows, which must wait for a commit.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { HydrationBoundaryProps } from "./hydration-boundary.mjs";
|
|
2
|
+
//#region src/hydration-boundary/hydration-boundary-react-server.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* `HydrationBoundary` in server components (the `react-server` export
|
|
5
|
+
* condition). With `client`, sends the request client's entries to the
|
|
6
|
+
* browser cache: pending entries cross as promises and stream in as they
|
|
7
|
+
* settle, and entries an earlier boundary already sent in this request are
|
|
8
|
+
* skipped. With `state`, writes that state, as the browser version does.
|
|
9
|
+
*/
|
|
10
|
+
export declare function HydrationBoundary(props: HydrationBoundaryProps): import("react").JSX.Element;
|
|
11
|
+
//#endregion
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Hydrate } from "./hydrate.mjs";
|
|
2
|
+
import { sentHashes } from "./sent.mjs";
|
|
3
|
+
import { dehydrate } from "@raf-query/core";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/hydration-boundary/hydration-boundary-react-server.tsx
|
|
6
|
+
/**
|
|
7
|
+
* `HydrationBoundary` in server components (the `react-server` export
|
|
8
|
+
* condition). With `client`, sends the request client's entries to the
|
|
9
|
+
* browser cache: pending entries cross as promises and stream in as they
|
|
10
|
+
* settle, and entries an earlier boundary already sent in this request are
|
|
11
|
+
* skipped. With `state`, writes that state, as the browser version does.
|
|
12
|
+
*/
|
|
13
|
+
function HydrationBoundary(props) {
|
|
14
|
+
if (props.client === void 0) return /* @__PURE__ */ jsx(Hydrate, {
|
|
15
|
+
options: props.options,
|
|
16
|
+
state: props.state,
|
|
17
|
+
children: props.children
|
|
18
|
+
});
|
|
19
|
+
const client = props.client;
|
|
20
|
+
const state = dehydrate(client, {
|
|
21
|
+
sent: sentHashes(client),
|
|
22
|
+
...props.options
|
|
23
|
+
});
|
|
24
|
+
return /* @__PURE__ */ jsx(Hydrate, {
|
|
25
|
+
state,
|
|
26
|
+
children: props.children
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { HydrationBoundary };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@raf-query/core";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/hydration-boundary/hydration-boundary.d.ts
|
|
4
|
+
export type HydrationBoundaryProps = {
|
|
5
|
+
readonly children?: ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* The request's server client (e.g. from React's `cache()`). Server
|
|
8
|
+
* components only.
|
|
9
|
+
*/
|
|
10
|
+
readonly client: QueryClient;
|
|
11
|
+
readonly options?: DehydrateOptions;
|
|
12
|
+
readonly state?: never;
|
|
13
|
+
} | {
|
|
14
|
+
readonly children?: ReactNode;
|
|
15
|
+
readonly client?: never;
|
|
16
|
+
readonly options?: HydrateOptions;
|
|
17
|
+
/** A loader's `dehydrate(qc)`. */
|
|
18
|
+
readonly state: DehydratedState;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Writes server data into the browser (or SSR) client.
|
|
22
|
+
*
|
|
23
|
+
* In a server component, pass the request's `client`. Its entries go
|
|
24
|
+
* through the RSC payload: pending entries cross as promises and stream in
|
|
25
|
+
* as they settle, and entries an earlier boundary already sent in this
|
|
26
|
+
* request are skipped. Server components get that build of the component
|
|
27
|
+
* through the package's `react-server` export condition.
|
|
28
|
+
*
|
|
29
|
+
* ```tsx
|
|
30
|
+
* const qc = getQueryClient();
|
|
31
|
+
* const comments = qc.prefetch(commentsQuery, { slug });
|
|
32
|
+
* return (
|
|
33
|
+
* <HydrationBoundary client={qc}>
|
|
34
|
+
* <Comments handle={comments} />
|
|
35
|
+
* </HydrationBoundary>
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* With loaders, such as React Router Framework Mode, pass the `state` the
|
|
40
|
+
* loader dehydrated:
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* export async function loader(args: Route.LoaderArgs) {
|
|
44
|
+
* const qc = new QueryClient();
|
|
45
|
+
* const post = await qc.ensure(postQuery, { slug: args.params.slug });
|
|
46
|
+
* return { dehydratedState: dehydrate(qc), post };
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* export default function Page(props: Route.ComponentProps) {
|
|
50
|
+
* const { dehydratedState, post } = props.loaderData;
|
|
51
|
+
* return (
|
|
52
|
+
* <HydrationBoundary state={dehydratedState}>
|
|
53
|
+
* <Post handle={post} />
|
|
54
|
+
* </HydrationBoundary>
|
|
55
|
+
* );
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* Pending entries cross as promises when the framework's serializer
|
|
60
|
+
* supports them (React Router's Single Fetch does). Nested boundaries
|
|
61
|
+
* are fine: each only writes what its `state` holds.
|
|
62
|
+
*/
|
|
63
|
+
export declare function HydrationBoundary(props: HydrationBoundaryProps): import("react").JSX.Element;
|
|
64
|
+
//#endregion
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Hydrate } from "./hydrate.mjs";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/hydration-boundary/hydration-boundary.tsx
|
|
5
5
|
/**
|
|
6
|
-
* Writes
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Writes server data into the browser (or SSR) client.
|
|
7
|
+
*
|
|
8
|
+
* In a server component, pass the request's `client`. Its entries go
|
|
9
|
+
* through the RSC payload: pending entries cross as promises and stream in
|
|
10
|
+
* as they settle, and entries an earlier boundary already sent in this
|
|
11
|
+
* request are skipped. Server components get that build of the component
|
|
12
|
+
* through the package's `react-server` export condition.
|
|
13
|
+
*
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const qc = getQueryClient();
|
|
16
|
+
* const comments = qc.prefetch(commentsQuery, { slug });
|
|
17
|
+
* return (
|
|
18
|
+
* <HydrationBoundary client={qc}>
|
|
19
|
+
* <Comments handle={comments} />
|
|
20
|
+
* </HydrationBoundary>
|
|
21
|
+
* );
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* With loaders, such as React Router Framework Mode, pass the `state` the
|
|
25
|
+
* loader dehydrated:
|
|
9
26
|
*
|
|
10
27
|
* ```tsx
|
|
11
28
|
* export async function loader(args: Route.LoaderArgs) {
|
|
@@ -29,6 +46,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
29
46
|
* are fine: each only writes what its `state` holds.
|
|
30
47
|
*/
|
|
31
48
|
function HydrationBoundary(props) {
|
|
49
|
+
if (props.state === void 0) throw new Error("HydrationBoundary needs `state` here. `client` works only in server components.");
|
|
32
50
|
return /* @__PURE__ */ jsx(Hydrate, {
|
|
33
51
|
options: props.options,
|
|
34
52
|
state: props.state,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
3
|
+
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
4
|
+
import { UseQueryResult, UseQueryResultWithData, useQuery } from "./use-query.mjs";
|
|
5
|
+
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
import "./index-shared.mjs";
|
|
7
|
+
import { HydrationBoundary } from "./hydration-boundary/hydration-boundary-react-server.mjs";
|
|
8
|
+
export * from "@raf-query/core";
|
|
9
|
+
export { HydrationBoundary, QueryClientProvider, QueryProvider, type UseQueryResult, type UseQueryResultWithData, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
3
|
+
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
4
|
+
import { useQuery } from "./use-query.mjs";
|
|
5
|
+
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
import { HydrationBoundary } from "./hydration-boundary/hydration-boundary-react-server.mjs";
|
|
7
|
+
export * from "@raf-query/core";
|
|
8
|
+
export { HydrationBoundary, QueryClientProvider, QueryProvider, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
3
|
+
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
4
|
+
import { UseQueryResult, UseQueryResultWithData, useQuery } from "./use-query.mjs";
|
|
5
|
+
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
export * from "@raf-query/core";
|
|
7
|
+
export { QueryClientProvider, QueryProvider, type UseQueryResult, type UseQueryResultWithData, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
3
|
+
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
4
|
+
import { useQuery } from "./use-query.mjs";
|
|
5
|
+
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
export * from "@raf-query/core";
|
|
7
|
+
export { QueryClientProvider, QueryProvider, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { QueryClient, QueryClientConfig, dehydrate, hydrate } from "./client.mjs";
|
|
2
|
-
import { Settled, allKeyed } from "./all-keyed.mjs";
|
|
3
1
|
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
4
3
|
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
5
|
-
import {
|
|
4
|
+
import { UseQueryResult, UseQueryResultWithData, useQuery } from "./use-query.mjs";
|
|
6
5
|
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
import "./index-shared.mjs";
|
|
7
|
+
import { HydrationBoundary } from "./hydration-boundary/hydration-boundary.mjs";
|
|
7
8
|
export * from "@raf-query/core";
|
|
8
|
-
export {
|
|
9
|
+
export { HydrationBoundary, QueryClientProvider, QueryProvider, type UseQueryResult, type UseQueryResultWithData, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { allKeyed } from "./all-keyed.mjs";
|
|
2
|
-
import { QueryClient, dehydrate, hydrate } from "./client.mjs";
|
|
3
1
|
import { QueryClientProvider, useQueryClient } from "./provider.mjs";
|
|
2
|
+
import { QueryProvider } from "./query-provider/query-provider.mjs";
|
|
4
3
|
import { useIsFetching } from "./use-is-fetching.mjs";
|
|
5
4
|
import { useQuery } from "./use-query.mjs";
|
|
6
5
|
import { useWaterfall } from "./use-waterfall.mjs";
|
|
6
|
+
import { HydrationBoundary } from "./hydration-boundary/hydration-boundary.mjs";
|
|
7
7
|
export * from "@raf-query/core";
|
|
8
|
-
export {
|
|
8
|
+
export { HydrationBoundary, QueryClientProvider, QueryProvider, useIsFetching, useQuery, useQueryClient, useWaterfall };
|
package/dist/provider.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Query } from "@raf-query/core";
|
|
2
|
-
//#region src/browser-requests.ts
|
|
2
|
+
//#region src/query-provider/browser-requests.ts
|
|
3
3
|
/**
|
|
4
4
|
* The digest Next.js gives a boundary that renders only in the browser
|
|
5
5
|
* (`next/dynamic` with `ssr: false`); it doesn't report those errors.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { QueryClientConfig } from "
|
|
1
|
+
import { QueryClientConfig } from "@raf-query/core";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
|
-
//#region src/query-provider.d.ts
|
|
3
|
+
//#region src/query-provider/query-provider.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The query client provider for React Server Components apps. Creates one
|
|
6
6
|
* client per server render and one per browser tab. The server render
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { QueryClientProvider } from "./provider.mjs";
|
|
2
|
+
import { QueryClientProvider } from "../provider.mjs";
|
|
4
3
|
import { requestInBrowserOnly } from "./browser-requests.mjs";
|
|
4
|
+
import { QueryClient } from "@raf-query/core";
|
|
5
5
|
import { useState } from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
//#region src/query-provider.tsx
|
|
7
|
+
//#region src/query-provider/query-provider.tsx
|
|
8
8
|
/**
|
|
9
9
|
* The query client provider for React Server Components apps. Creates one
|
|
10
10
|
* client per server render and one per browser tab. The server render
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { QueryClient } from "
|
|
2
|
-
import { DehydrateOptions, DehydratedState, HydrateOptions, QueryHandle } from "@raf-query/core";
|
|
1
|
+
import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient, QueryHandle } from "@raf-query/core";
|
|
3
2
|
import { AnyRouter } from "@tanstack/react-router";
|
|
4
3
|
//#region src/tanstack-router-shared.d.ts
|
|
5
4
|
declare module "@tanstack/react-router" {
|
package/dist/use-query.d.mts
CHANGED
|
@@ -1,67 +1,6 @@
|
|
|
1
|
-
import { DataOf, ErrorOf,
|
|
1
|
+
import { DataOf, ErrorOf, QueryFactory, QueryHandle, QueryHandleWithData, ThrowsOnError, UseQueryControls, UseQueryOptions, UseQueryThrowOptions } from "@raf-query/core";
|
|
2
2
|
import { Result } from "effect";
|
|
3
3
|
//#region src/use-query.d.ts
|
|
4
|
-
/** `refetchInterval`, `refetchOnWindowFocus`, `refetchOnReconnect`, `whilePending`. */
|
|
5
|
-
export type UseQueryOptions = QueryObserver.Options;
|
|
6
|
-
/**
|
|
7
|
-
* `throwOnError` only when {@link ErrorOf} is typed (Effect `queryFn`).
|
|
8
|
-
* Promise factories always throw; the option is not part of their options.
|
|
9
|
-
*/
|
|
10
|
-
export type UseQueryThrowOptions<TFactory extends QueryFactory> = HasTypedError<TFactory> extends true ? {
|
|
11
|
-
/**
|
|
12
|
-
* When `false`, the first tuple slot is a `Result` instead of a
|
|
13
|
-
* rejecting promise. Omit to use the client's default (`false`
|
|
14
|
-
* with a `layer`, `true` without).
|
|
15
|
-
*/
|
|
16
|
-
readonly throwOnError?: boolean;
|
|
17
|
-
} : {
|
|
18
|
-
readonly throwOnError?: never;
|
|
19
|
-
};
|
|
20
|
-
/** The second element of {@link useQuery}'s result. */
|
|
21
|
-
export interface QueryControls<TFactory extends QueryFactory> {
|
|
22
|
-
/** Error of the last failed request. Existing data stays readable. */
|
|
23
|
-
readonly error: unknown;
|
|
24
|
-
/** Stable string form of the handle's key, for `key` props. */
|
|
25
|
-
readonly hash: string;
|
|
26
|
-
/** Input of the data in the promise; differs from the handle's while `isPrevious`. */
|
|
27
|
-
readonly input: InputOf<TFactory>;
|
|
28
|
-
/** A request is in flight: first load, new input, or background refetch. */
|
|
29
|
-
readonly isFetching: boolean;
|
|
30
|
-
/** No data yet for the handle's input. */
|
|
31
|
-
readonly isPending: boolean;
|
|
32
|
-
/** The promise holds a previous input's data (`whilePending: "previous"`). */
|
|
33
|
-
readonly isPrevious: boolean;
|
|
34
|
-
/** The data is older than `staleTime`, or was invalidated. */
|
|
35
|
-
readonly isStale: boolean;
|
|
36
|
-
/** Key of the data in the promise; differs from the handle's while `isPrevious`. */
|
|
37
|
-
readonly key: QueryKey;
|
|
38
|
-
/** Refetch now. Resolves when the request settles; never rejects. */
|
|
39
|
-
refetch(): Promise<void>;
|
|
40
|
-
/** When the data in the promise was fetched (ms since epoch); `0` before that. */
|
|
41
|
-
readonly updatedAt: number;
|
|
42
|
-
}
|
|
43
|
-
/** Extra controls for factories that return `infiniteQueryOptions(...)`. */
|
|
44
|
-
export interface PagingControls {
|
|
45
|
-
fetchNextPage(): Promise<void>;
|
|
46
|
-
fetchPreviousPage(): Promise<void>;
|
|
47
|
-
readonly hasNextPage: boolean;
|
|
48
|
-
readonly hasPreviousPage: boolean;
|
|
49
|
-
readonly isFetchingNextPage: boolean;
|
|
50
|
-
readonly isFetchingPreviousPage: boolean;
|
|
51
|
-
}
|
|
52
|
-
export type UseQueryControls<TFactory extends QueryFactory> = IsPaged<TFactory> extends true ? QueryControls<TFactory> & PagingControls : QueryControls<TFactory>;
|
|
53
|
-
/**
|
|
54
|
-
* `true` when the factory's error channel is typed (Effect `queryFn`), not
|
|
55
|
-
* `unknown` (promise / plain value).
|
|
56
|
-
*/
|
|
57
|
-
export type HasTypedError<TFactory extends QueryFactory> = unknown extends ErrorOf<TFactory> ? false : true;
|
|
58
|
-
/**
|
|
59
|
-
* Whether this read throws on failure. Untyped errors always throw. Typed
|
|
60
|
-
* errors follow `options.throwOnError`, else the client's default (`false`
|
|
61
|
-
* with a `layer`, `true` without). Types treat an omitted flag as `false`
|
|
62
|
-
* (Result), matching a client with a `layer`.
|
|
63
|
-
*/
|
|
64
|
-
export type ThrowsOnError<TFactory extends QueryFactory, TThrow extends boolean | undefined> = HasTypedError<TFactory> extends false ? true : TThrow extends boolean ? TThrow : false;
|
|
65
4
|
export type UseQueryResult<TFactory extends QueryFactory, TThrow extends boolean | undefined = undefined> = ThrowsOnError<TFactory, TThrow> extends true ? readonly [promise: Promise<DataOf<TFactory>>, controls: UseQueryControls<TFactory>] : readonly [promise: Promise<Result.Result<DataOf<TFactory>, ErrorOf<TFactory>>>, controls: UseQueryControls<TFactory>];
|
|
66
5
|
/** {@link useQuery}'s result for a handle from `ensure` or `fetch`. */
|
|
67
6
|
export type UseQueryResultWithData<TFactory extends QueryFactory, TThrow extends boolean | undefined = undefined> = ThrowsOnError<TFactory, TThrow> extends true ? readonly [data: DataOf<TFactory>, controls: UseQueryControls<TFactory>] : readonly [result: Result.Result<DataOf<TFactory>, ErrorOf<TFactory>>, controls: UseQueryControls<TFactory>];
|
package/dist/use-query.mjs
CHANGED
|
@@ -1,31 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useQueryClient } from "./provider.mjs";
|
|
3
|
-
import { assertSent } from "./browser-requests.mjs";
|
|
4
|
-
import { Query, QueryObserver,
|
|
5
|
-
import { Effect, Result } from "effect";
|
|
3
|
+
import { assertSent } from "./query-provider/browser-requests.mjs";
|
|
4
|
+
import { Query, QueryObserver, promiseControls, resultThenable } from "@raf-query/core";
|
|
6
5
|
import { use, useEffect, useState, useSyncExternalStore } from "react";
|
|
7
6
|
//#region src/use-query.ts
|
|
8
7
|
function queryFor(client, factory, input) {
|
|
9
8
|
const args = [input];
|
|
10
9
|
return client.getQuery(factory, ...args);
|
|
11
10
|
}
|
|
12
|
-
const commands = /* @__PURE__ */ new WeakMap();
|
|
13
|
-
/** One stable Promise function per command Effect, so identities track the query's. */
|
|
14
|
-
function commandFor(effect) {
|
|
15
|
-
let command = commands.get(effect);
|
|
16
|
-
if (!command) {
|
|
17
|
-
command = () => Effect.runPromise(effect);
|
|
18
|
-
commands.set(effect, command);
|
|
19
|
-
}
|
|
20
|
-
return command;
|
|
21
|
-
}
|
|
22
|
-
/** `tracked`, with the observer's command Effects as Promise functions. */
|
|
23
|
-
function withPromiseCommands(tracked) {
|
|
24
|
-
return new Proxy(tracked, { get: (target, name, receiver) => {
|
|
25
|
-
if (name === "fetchNextPage" || name === "fetchPreviousPage" || name === "refetch") return commandFor(target[name]);
|
|
26
|
-
return Reflect.get(target, name, receiver);
|
|
27
|
-
} });
|
|
28
|
-
}
|
|
29
11
|
function storeFor(query, options) {
|
|
30
12
|
const observer = QueryObserver.makeUnsafe(query, options);
|
|
31
13
|
return {
|
|
@@ -34,29 +16,6 @@ function storeFor(query, options) {
|
|
|
34
16
|
subscribe: (onChange) => QueryObserver.subscribeUnsafe(observer, onChange)
|
|
35
17
|
};
|
|
36
18
|
}
|
|
37
|
-
/**
|
|
38
|
-
* One `Result` thenable per data thenable, so `use()` sees a stable identity
|
|
39
|
-
* across re-renders the same way it does for the data promise.
|
|
40
|
-
*/
|
|
41
|
-
const resultThenables = /* @__PURE__ */ new WeakMap();
|
|
42
|
-
function asResultThenable(promise) {
|
|
43
|
-
const cached = resultThenables.get(promise);
|
|
44
|
-
if (cached) return cached;
|
|
45
|
-
let next;
|
|
46
|
-
if (promise.status === "fulfilled") next = fulfilled(Result.succeed(promise.value));
|
|
47
|
-
else if (promise.status === "rejected") next = fulfilled(Result.fail(promise.reason));
|
|
48
|
-
else {
|
|
49
|
-
const deferred = pending();
|
|
50
|
-
promise.then((value) => {
|
|
51
|
-
deferred.resolve(Result.succeed(value));
|
|
52
|
-
}, (error) => {
|
|
53
|
-
deferred.resolve(Result.fail(error));
|
|
54
|
-
});
|
|
55
|
-
next = deferred.promise;
|
|
56
|
-
}
|
|
57
|
-
resultThenables.set(promise, next);
|
|
58
|
-
return next;
|
|
59
|
-
}
|
|
60
19
|
function useQuery(factory, handle, options = {}) {
|
|
61
20
|
const client = useQueryClient();
|
|
62
21
|
const query = queryFor(client, factory, handle.input);
|
|
@@ -86,11 +45,11 @@ function useQuery(factory, handle, options = {}) {
|
|
|
86
45
|
whilePending
|
|
87
46
|
]);
|
|
88
47
|
QueryObserver.trackProp(observer, "promise");
|
|
89
|
-
const controls =
|
|
48
|
+
const controls = promiseControls(QueryObserver.trackResult(observer, result));
|
|
90
49
|
const throwOnError = options.throwOnError ?? client.throwOnError;
|
|
91
50
|
const withData = "data" in handle;
|
|
92
51
|
if (!throwOnError) {
|
|
93
|
-
const resultPromise =
|
|
52
|
+
const resultPromise = resultThenable(result.promise);
|
|
94
53
|
if (withData) return [use(resultPromise), controls];
|
|
95
54
|
return [resultPromise, controls];
|
|
96
55
|
}
|
package/dist/use-waterfall.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ import { InputArgs, QueryFactory, QueryHandle } from "@raf-query/core";
|
|
|
5
5
|
* at render time (an id from a parent query's data). Each call is a request
|
|
6
6
|
* waterfall: prefer starting the query in a loader or server component.
|
|
7
7
|
* Like `prefetch` in a loader, it refetches stale cached data in the
|
|
8
|
-
* background, once per mount and input. Under
|
|
8
|
+
* background, once per mount and input. Under `QueryProvider` it
|
|
9
9
|
* starts nothing on the server: the reader's Suspense boundary renders its
|
|
10
10
|
* fallback there, and the query loads in the browser.
|
|
11
11
|
*
|
package/dist/use-waterfall.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useQueryClient } from "./provider.mjs";
|
|
3
|
-
import { startsRequests } from "./browser-requests.mjs";
|
|
3
|
+
import { startsRequests } from "./query-provider/browser-requests.mjs";
|
|
4
4
|
import { Query } from "@raf-query/core";
|
|
5
5
|
import { useState } from "react";
|
|
6
6
|
//#region src/use-waterfall.ts
|
|
@@ -15,7 +15,7 @@ const waitedFor = /* @__PURE__ */ new WeakSet();
|
|
|
15
15
|
* at render time (an id from a parent query's data). Each call is a request
|
|
16
16
|
* waterfall: prefer starting the query in a loader or server component.
|
|
17
17
|
* Like `prefetch` in a loader, it refetches stale cached data in the
|
|
18
|
-
* background, once per mount and input. Under
|
|
18
|
+
* background, once per mount and input. Under `QueryProvider` it
|
|
19
19
|
* starts nothing on the server: the reader's Suspense boundary renders its
|
|
20
20
|
* fallback there, and the query loads in the browser.
|
|
21
21
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@raf-query/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "React bindings for raf-query, a render-as-you-fetch query library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"query",
|
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
"type": "module",
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"exports": {
|
|
35
|
-
".":
|
|
35
|
+
".": {
|
|
36
|
+
"react-server": "./dist/index-react-server.mjs",
|
|
37
|
+
"default": "./dist/index.mjs"
|
|
38
|
+
},
|
|
36
39
|
"./devtools": "./dist/devtools.mjs",
|
|
37
|
-
"./rsc": "./dist/rsc.mjs",
|
|
38
|
-
"./react-router": "./dist/react-router.mjs",
|
|
39
40
|
"./tanstack-router": {
|
|
40
41
|
"workerd": "./dist/tanstack-router.mjs",
|
|
41
42
|
"worker": "./dist/tanstack-router.mjs",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
}
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@raf-query/core": "0.
|
|
51
|
+
"@raf-query/core": "0.10.1"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
54
|
"@tanstack/react-router": "^1.170.0",
|
package/dist/all-keyed.d.mts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
//#region src/all-keyed.d.ts
|
|
2
|
-
/** The resolved form of a record passed to {@link allKeyed}. */
|
|
3
|
-
export type Settled<TRecord> = { -readonly [TKey in keyof TRecord]: Awaited<TRecord[TKey]>; };
|
|
4
|
-
/**
|
|
5
|
-
* Ponyfill of the TC39 `Promise.allKeyed` proposal: a record of promises in,
|
|
6
|
-
* a promise of the same record out, rejecting on the first failure.
|
|
7
|
-
*
|
|
8
|
-
* ```ts
|
|
9
|
-
* const data = await allKeyed({
|
|
10
|
-
* post: qc.ensure(postQuery, { slug }),
|
|
11
|
-
* author: qc.ensure(authorQuery, { slug }),
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export declare function allKeyed<TRecord extends {
|
|
16
|
-
readonly [key: string]: unknown;
|
|
17
|
-
}>(record: TRecord): Promise<Settled<TRecord>>;
|
|
18
|
-
//#endregion
|
package/dist/all-keyed.mjs
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
//#region src/all-keyed.ts
|
|
2
|
-
/**
|
|
3
|
-
* Ponyfill of the TC39 `Promise.allKeyed` proposal: a record of promises in,
|
|
4
|
-
* a promise of the same record out, rejecting on the first failure.
|
|
5
|
-
*
|
|
6
|
-
* ```ts
|
|
7
|
-
* const data = await allKeyed({
|
|
8
|
-
* post: qc.ensure(postQuery, { slug }),
|
|
9
|
-
* author: qc.ensure(authorQuery, { slug }),
|
|
10
|
-
* });
|
|
11
|
-
* ```
|
|
12
|
-
*/
|
|
13
|
-
async function allKeyed(record) {
|
|
14
|
-
const keys = Object.keys(record);
|
|
15
|
-
const values = await Promise.all(keys.map((key) => record[key]));
|
|
16
|
-
return Object.fromEntries(keys.map((key, index) => [key, values[index]]));
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { allKeyed };
|
package/dist/client.d.mts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import { DataOf, DehydrateOptions, DehydratedState, HydrateOptions, InputArgs, InputOf, LoadOptions, PagedQueryFactory, Query, QueryCache, QueryFactory, QueryHandle, QueryHandleWithData } from "@raf-query/core";
|
|
2
|
-
import { Effect, Layer } from "effect";
|
|
3
|
-
//#region src/client.d.ts
|
|
4
|
-
export interface QueryClientConfig<TServices = never> extends QueryCache.Config {
|
|
5
|
-
/**
|
|
6
|
-
* Services for queries whose `queryFn` returns an Effect. Built with the
|
|
7
|
-
* client, so it must build synchronously; `dispose()` runs its
|
|
8
|
-
* finalizers.
|
|
9
|
-
*/
|
|
10
|
-
readonly layer?: Layer.Layer<TServices>;
|
|
11
|
-
/** Called with every failed request, including failed prefetches. */
|
|
12
|
-
onError?(error: unknown, query: Query.Query): void;
|
|
13
|
-
/**
|
|
14
|
-
* When `false`, `useQuery` for an Effect `queryFn` (a typed `ErrorOf`)
|
|
15
|
-
* returns a `Result` in the first tuple slot instead of a promise that
|
|
16
|
-
* rejects. Defaults to `false` when `layer` is set, `true` otherwise.
|
|
17
|
-
* Promise `queryFn`s always throw; this flag does not apply to them.
|
|
18
|
-
*/
|
|
19
|
-
readonly throwOnError?: boolean;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* The query cache, with Promise methods. Create one per request on the
|
|
23
|
-
* server and one per browser tab. `effect` is the same cache's Effect API.
|
|
24
|
-
* Its verbs take factories whose `queryFn` needs at most `TServices`, the
|
|
25
|
-
* services of `config.layer`.
|
|
26
|
-
*/
|
|
27
|
-
export declare class QueryClient<TServices = never> {
|
|
28
|
-
#private;
|
|
29
|
-
/** The Effect-native cache behind this client. */
|
|
30
|
-
readonly effect: QueryCache.QueryCache;
|
|
31
|
-
readonly isServer: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Default for Effect `useQuery` reads. See
|
|
34
|
-
* {@link QueryClientConfig.throwOnError}.
|
|
35
|
-
*/
|
|
36
|
-
readonly throwOnError: boolean;
|
|
37
|
-
constructor(config?: QueryClientConfig<TServices>);
|
|
38
|
-
/**
|
|
39
|
-
* The cache entry for a factory call, created if missing. Doesn't fetch.
|
|
40
|
-
* For bindings; apps use the verbs.
|
|
41
|
-
*/
|
|
42
|
-
getQuery<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Query.Query<TFactory>;
|
|
43
|
-
/**
|
|
44
|
-
* Start a query without waiting and return its handle. Fresh data is
|
|
45
|
-
* reused; stale data refetches in the background (in the browser only).
|
|
46
|
-
* Errors surface where the data is read, never here.
|
|
47
|
-
*/
|
|
48
|
-
prefetch<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): QueryHandle<TFactory>;
|
|
49
|
-
/**
|
|
50
|
-
* {@link fetch} without waiting on stale data: start a query and wait for
|
|
51
|
-
* it on a cache miss. Stale cached data resolves immediately and
|
|
52
|
-
* revalidates in the browser. Rejects if that request fails.
|
|
53
|
-
*/
|
|
54
|
-
ensure<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<QueryHandleWithData<TFactory>>;
|
|
55
|
-
/** {@link ensure}, loading `options.pages` pages of a paged query. */
|
|
56
|
-
ensure<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<QueryHandleWithData<TFactory>>;
|
|
57
|
-
/**
|
|
58
|
-
* Start a query and resolve to a handle holding its data. Waits on a cache
|
|
59
|
-
* miss and on stale data (on the server, only invalidated data), so the
|
|
60
|
-
* data is fresh. Rejects if that request fails.
|
|
61
|
-
*/
|
|
62
|
-
fetch<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): Promise<QueryHandleWithData<TFactory>>;
|
|
63
|
-
/** {@link fetch}, loading `options.pages` pages of a paged query. */
|
|
64
|
-
fetch<TFactory extends PagedQueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, options: LoadOptions): Promise<QueryHandleWithData<TFactory>>;
|
|
65
|
-
/**
|
|
66
|
-
* Mark queries stale and refetch the ones being read. Resolves once those
|
|
67
|
-
* refetches settle, so an action stays pending until fresh data is on
|
|
68
|
-
* screen. Takes a factory and its input, or a {@link QueryCache.Filter}.
|
|
69
|
-
*/
|
|
70
|
-
invalidate<TFactory extends QueryFactory<TServices>>(...target: QueryCache.Target<TFactory>): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Drop queries' data and errors, as if they were never fetched. Read ones
|
|
73
|
-
* suspend and refetch; resolves once those refetches settle.
|
|
74
|
-
*/
|
|
75
|
-
reset<TFactory extends QueryFactory<TServices>>(...target: QueryCache.Target<TFactory>): Promise<void>;
|
|
76
|
-
/**
|
|
77
|
-
* Remove queries from the cache and abort their requests. Readers keep the
|
|
78
|
-
* removed entry until they render again.
|
|
79
|
-
*/
|
|
80
|
-
remove<TFactory extends QueryFactory<TServices>>(...target: QueryCache.Target<TFactory>): void;
|
|
81
|
-
/** Write data for a factory call. Readers re-render without suspending. */
|
|
82
|
-
setData<TFactory extends QueryFactory<TServices>>(factory: TFactory, input: InputOf<TFactory>, updater: QueryCache.Updater<DataOf<TFactory>>): void;
|
|
83
|
-
/**
|
|
84
|
-
* Cached data for a factory call, or `undefined` if there is none. Data can
|
|
85
|
-
* itself be `undefined`; `Query.getUnsafe(getQuery(...)).hasData` tells
|
|
86
|
-
* them apart.
|
|
87
|
-
*/
|
|
88
|
-
getData<TFactory extends QueryFactory<TServices>>(factory: TFactory, ...args: InputArgs<TFactory>): DataOf<TFactory> | undefined;
|
|
89
|
-
/** Every entry, for devtools and integrations. */
|
|
90
|
-
getAll(): ReadonlyArray<Query.Query>;
|
|
91
|
-
/**
|
|
92
|
-
* How many entries have a request in flight: all of them, or those
|
|
93
|
-
* matching `filter`. For global loading indicators.
|
|
94
|
-
*/
|
|
95
|
-
isFetching(filter?: QueryCache.Filter): number;
|
|
96
|
-
/** Listen to entries being added, updated, and removed. */
|
|
97
|
-
subscribe(listener: (event: QueryCache.Event) => void): () => void;
|
|
98
|
-
/** Drop every entry and abort in-flight requests. */
|
|
99
|
-
clear(): void;
|
|
100
|
-
/**
|
|
101
|
-
* Start refetching read, stale queries on window focus and reconnect.
|
|
102
|
-
* Returns the matching unmount. Providers call this; mounts are counted.
|
|
103
|
-
*/
|
|
104
|
-
mount(): () => void;
|
|
105
|
-
/**
|
|
106
|
-
* Run an Effect with the cache (`QueryCache`) and the services of
|
|
107
|
-
* `config.layer`, as `Effect.runPromise` does: it rejects with the
|
|
108
|
-
* Effect's failure, or its defect. For an app's loaders and actions.
|
|
109
|
-
*/
|
|
110
|
-
runPromise<A, E>(effect: Effect.Effect<A, E, QueryCache.QueryCache | TServices>): Promise<A>;
|
|
111
|
-
/**
|
|
112
|
-
* Close the client: interrupt every request and timer, and release the
|
|
113
|
-
* layer's services. Resolves once the layer's finalizers have run.
|
|
114
|
-
*/
|
|
115
|
-
dispose(): Promise<void>;
|
|
116
|
-
}
|
|
117
|
-
/** Snapshot the cache for transfer to another client (server → browser). */
|
|
118
|
-
export declare function dehydrate(client: QueryClient, options?: DehydrateOptions): DehydratedState;
|
|
119
|
-
/**
|
|
120
|
-
* Write dehydrated entries into a client. Existing entries only take newer
|
|
121
|
-
* data; pending entries resume the sender's request.
|
|
122
|
-
*/
|
|
123
|
-
export declare function hydrate(client: QueryClient, state: DehydratedState, options?: HydrateOptions): void;
|
|
124
|
-
//#endregion
|
package/dist/client.mjs
DELETED
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { QueryCache } from "@raf-query/core";
|
|
2
|
-
import { Context, Effect, Exit, Layer, Option, Predicate, Scope } from "effect";
|
|
3
|
-
//#region src/client.ts
|
|
4
|
-
/**
|
|
5
|
-
* A verb's Effect, run by a client. Its requirement is the factory's
|
|
6
|
-
* `ServicesOf`, which the client's verbs only accept when its `layer`
|
|
7
|
-
* provides them.
|
|
8
|
-
*/
|
|
9
|
-
function provided(effect) {
|
|
10
|
-
return effect;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Run a verb that waits on a request. A cancelled request rejects with an
|
|
14
|
-
* `AbortError`, as an aborted `fetch` does, not with the Effect API's
|
|
15
|
-
* `Query.CancelledError`.
|
|
16
|
-
*/
|
|
17
|
-
function runLoad(effect) {
|
|
18
|
-
return Effect.runPromise(effect).catch((error) => {
|
|
19
|
-
throw Predicate.isTagged(error, "CancelledError") ? new DOMException("The query was cancelled", "AbortError") : error;
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
/** `ensure` / `fetch` arguments, forwarded to the cache's same verb. */
|
|
23
|
-
function loadArgs(input, options) {
|
|
24
|
-
return [input, options];
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* The query cache, with Promise methods. Create one per request on the
|
|
28
|
-
* server and one per browser tab. `effect` is the same cache's Effect API.
|
|
29
|
-
* Its verbs take factories whose `queryFn` needs at most `TServices`, the
|
|
30
|
-
* services of `config.layer`.
|
|
31
|
-
*/
|
|
32
|
-
var QueryClient = class {
|
|
33
|
-
/** The Effect-native cache behind this client. */
|
|
34
|
-
effect;
|
|
35
|
-
isServer;
|
|
36
|
-
/**
|
|
37
|
-
* Default for Effect `useQuery` reads. See
|
|
38
|
-
* {@link QueryClientConfig.throwOnError}.
|
|
39
|
-
*/
|
|
40
|
-
throwOnError;
|
|
41
|
-
/**
|
|
42
|
-
* The cache and the layer's services. Typed `never` so clients of any
|
|
43
|
-
* `TServices` stay assignable to each other; `runPromise` restores it.
|
|
44
|
-
*/
|
|
45
|
-
#context;
|
|
46
|
-
/**
|
|
47
|
-
* Owns the cache's fibers, mounts and the layer's services; lives until
|
|
48
|
-
* `dispose()`.
|
|
49
|
-
*/
|
|
50
|
-
#scope = Scope.makeUnsafe();
|
|
51
|
-
constructor(config = {}) {
|
|
52
|
-
const cache = QueryCache.layer(config);
|
|
53
|
-
const services = Effect.runSync(Layer.buildWithScope(config.layer ? Layer.provideMerge(cache, config.layer) : cache, this.#scope));
|
|
54
|
-
this.#context = services;
|
|
55
|
-
this.effect = Context.get(services, QueryCache.QueryCache);
|
|
56
|
-
this.isServer = this.effect.isServer;
|
|
57
|
-
this.throwOnError = config.throwOnError ?? config.layer === void 0;
|
|
58
|
-
const onError = config.onError;
|
|
59
|
-
if (onError) this.effect.subscribeUnsafe((event) => {
|
|
60
|
-
if (event.type === "failed") onError(event.error, event.query);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* The cache entry for a factory call, created if missing. Doesn't fetch.
|
|
65
|
-
* For bindings; apps use the verbs.
|
|
66
|
-
*/
|
|
67
|
-
getQuery(factory, ...args) {
|
|
68
|
-
return this.effect.getQueryUnsafe(factory, ...args);
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Start a query without waiting and return its handle. Fresh data is
|
|
72
|
-
* reused; stale data refetches in the background (in the browser only).
|
|
73
|
-
* Errors surface where the data is read, never here.
|
|
74
|
-
*/
|
|
75
|
-
prefetch(factory, ...args) {
|
|
76
|
-
return Effect.runSync(provided(this.effect.prefetch(factory, ...args)));
|
|
77
|
-
}
|
|
78
|
-
ensure(factory, input, options) {
|
|
79
|
-
return runLoad(provided(this.effect.ensure(factory, ...loadArgs(input, options))));
|
|
80
|
-
}
|
|
81
|
-
fetch(factory, input, options) {
|
|
82
|
-
return runLoad(provided(this.effect.fetch(factory, ...loadArgs(input, options))));
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Mark queries stale and refetch the ones being read. Resolves once those
|
|
86
|
-
* refetches settle, so an action stays pending until fresh data is on
|
|
87
|
-
* screen. Takes a factory and its input, or a {@link QueryCache.Filter}.
|
|
88
|
-
*/
|
|
89
|
-
invalidate(...target) {
|
|
90
|
-
return Effect.runPromise(this.effect.invalidate(...target));
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Drop queries' data and errors, as if they were never fetched. Read ones
|
|
94
|
-
* suspend and refetch; resolves once those refetches settle.
|
|
95
|
-
*/
|
|
96
|
-
reset(...target) {
|
|
97
|
-
return Effect.runPromise(this.effect.reset(...target));
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Remove queries from the cache and abort their requests. Readers keep the
|
|
101
|
-
* removed entry until they render again.
|
|
102
|
-
*/
|
|
103
|
-
remove(...target) {
|
|
104
|
-
Effect.runSync(this.effect.remove(...target));
|
|
105
|
-
}
|
|
106
|
-
/** Write data for a factory call. Readers re-render without suspending. */
|
|
107
|
-
setData(factory, input, updater) {
|
|
108
|
-
Effect.runSync(this.effect.setData(factory, input, updater));
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Cached data for a factory call, or `undefined` if there is none. Data can
|
|
112
|
-
* itself be `undefined`; `Query.getUnsafe(getQuery(...)).hasData` tells
|
|
113
|
-
* them apart.
|
|
114
|
-
*/
|
|
115
|
-
getData(factory, ...args) {
|
|
116
|
-
return Option.getOrUndefined(Effect.runSync(this.effect.getData(factory, ...args)));
|
|
117
|
-
}
|
|
118
|
-
/** Every entry, for devtools and integrations. */
|
|
119
|
-
getAll() {
|
|
120
|
-
return Effect.runSync(this.effect.all);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* How many entries have a request in flight: all of them, or those
|
|
124
|
-
* matching `filter`. For global loading indicators.
|
|
125
|
-
*/
|
|
126
|
-
isFetching(filter) {
|
|
127
|
-
return this.effect.isFetchingUnsafe(filter);
|
|
128
|
-
}
|
|
129
|
-
/** Listen to entries being added, updated, and removed. */
|
|
130
|
-
subscribe(listener) {
|
|
131
|
-
return this.effect.subscribeUnsafe(listener);
|
|
132
|
-
}
|
|
133
|
-
/** Drop every entry and abort in-flight requests. */
|
|
134
|
-
clear() {
|
|
135
|
-
Effect.runSync(this.effect.clear);
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Start refetching read, stale queries on window focus and reconnect.
|
|
139
|
-
* Returns the matching unmount. Providers call this; mounts are counted.
|
|
140
|
-
*/
|
|
141
|
-
mount() {
|
|
142
|
-
const scope = Scope.forkUnsafe(this.#scope);
|
|
143
|
-
Effect.runSync(this.effect.mount.pipe(Scope.provide(scope)));
|
|
144
|
-
return () => {
|
|
145
|
-
Effect.runSync(Scope.close(scope, Exit.void));
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Run an Effect with the cache (`QueryCache`) and the services of
|
|
150
|
-
* `config.layer`, as `Effect.runPromise` does: it rejects with the
|
|
151
|
-
* Effect's failure, or its defect. For an app's loaders and actions.
|
|
152
|
-
*/
|
|
153
|
-
runPromise(effect) {
|
|
154
|
-
return Effect.runPromiseWith(this.#context)(effect);
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Close the client: interrupt every request and timer, and release the
|
|
158
|
-
* layer's services. Resolves once the layer's finalizers have run.
|
|
159
|
-
*/
|
|
160
|
-
dispose() {
|
|
161
|
-
return Effect.runPromise(Scope.close(this.#scope, Exit.void));
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
/** Snapshot the cache for transfer to another client (server → browser). */
|
|
165
|
-
function dehydrate(client, options) {
|
|
166
|
-
return Effect.runSync(client.effect.dehydrate(options));
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Write dehydrated entries into a client. Existing entries only take newer
|
|
170
|
-
* data; pending entries resume the sender's request.
|
|
171
|
-
*/
|
|
172
|
-
function hydrate(client, state, options) {
|
|
173
|
-
Effect.runSync(client.effect.hydrate(state, options));
|
|
174
|
-
}
|
|
175
|
-
//#endregion
|
|
176
|
-
export { QueryClient, dehydrate, hydrate };
|
package/dist/react-router.d.mts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { DehydratedState, HydrateOptions } from "@raf-query/core";
|
|
2
|
-
import { ReactNode } from "react";
|
|
3
|
-
//#region src/react-router.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Writes a loader's dehydrated cache into the browser (or SSR) client.
|
|
6
|
-
* Use it with React Router Framework Mode: start queries in the loader,
|
|
7
|
-
* `dehydrate` the request's client, and pass that state here.
|
|
8
|
-
*
|
|
9
|
-
* ```tsx
|
|
10
|
-
* export async function loader(args: Route.LoaderArgs) {
|
|
11
|
-
* const qc = new QueryClient();
|
|
12
|
-
* const post = await qc.ensure(postQuery, { slug: args.params.slug });
|
|
13
|
-
* return { dehydratedState: dehydrate(qc), post };
|
|
14
|
-
* }
|
|
15
|
-
*
|
|
16
|
-
* export default function Page(props: Route.ComponentProps) {
|
|
17
|
-
* const { dehydratedState, post } = props.loaderData;
|
|
18
|
-
* return (
|
|
19
|
-
* <HydrationBoundary state={dehydratedState}>
|
|
20
|
-
* <Post handle={post} />
|
|
21
|
-
* </HydrationBoundary>
|
|
22
|
-
* );
|
|
23
|
-
* }
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Pending entries cross as promises when the framework's serializer
|
|
27
|
-
* supports them (React Router's Single Fetch does). Nested boundaries
|
|
28
|
-
* are fine: each only writes what its `state` holds.
|
|
29
|
-
*/
|
|
30
|
-
export declare function HydrationBoundary(props: {
|
|
31
|
-
readonly children?: ReactNode;
|
|
32
|
-
readonly options?: HydrateOptions;
|
|
33
|
-
readonly state: DehydratedState;
|
|
34
|
-
}): import("react").JSX.Element;
|
|
35
|
-
//#endregion
|
package/dist/rsc.d.mts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from "./client.mjs";
|
|
2
|
-
import { QueryProvider } from "./query-provider.mjs";
|
|
3
|
-
import { DehydrateOptions } from "@raf-query/core";
|
|
4
|
-
import { ReactNode } from "react";
|
|
5
|
-
//#region src/rsc.d.ts
|
|
6
|
-
/**
|
|
7
|
-
* Server component: sends the request client's entries to the browser cache.
|
|
8
|
-
* Pending entries cross as promises and stream in as they settle. Entries an
|
|
9
|
-
* earlier boundary already sent in this request are skipped.
|
|
10
|
-
*
|
|
11
|
-
* ```tsx
|
|
12
|
-
* const qc = getQueryClient();
|
|
13
|
-
* const comments = qc.prefetch(commentsQuery, { slug });
|
|
14
|
-
* return (
|
|
15
|
-
* <HydrationBoundary client={qc}>
|
|
16
|
-
* <Comments handle={comments} />
|
|
17
|
-
* </HydrationBoundary>
|
|
18
|
-
* );
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export declare function HydrationBoundary(props: {
|
|
22
|
-
readonly children?: ReactNode;
|
|
23
|
-
/** The request's server client (e.g. from React's `cache()`). */
|
|
24
|
-
readonly client: QueryClient;
|
|
25
|
-
readonly options?: DehydrateOptions;
|
|
26
|
-
}): import("react").JSX.Element;
|
|
27
|
-
//#endregion
|
|
28
|
-
export { QueryProvider };
|
package/dist/rsc.mjs
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { dehydrate } from "./client.mjs";
|
|
2
|
-
import { Hydrate } from "./hydrate.mjs";
|
|
3
|
-
import { sentHashes } from "./sent.mjs";
|
|
4
|
-
import { QueryProvider } from "./query-provider.mjs";
|
|
5
|
-
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
//#region src/rsc.tsx
|
|
7
|
-
/**
|
|
8
|
-
* Server component: sends the request client's entries to the browser cache.
|
|
9
|
-
* Pending entries cross as promises and stream in as they settle. Entries an
|
|
10
|
-
* earlier boundary already sent in this request are skipped.
|
|
11
|
-
*
|
|
12
|
-
* ```tsx
|
|
13
|
-
* const qc = getQueryClient();
|
|
14
|
-
* const comments = qc.prefetch(commentsQuery, { slug });
|
|
15
|
-
* return (
|
|
16
|
-
* <HydrationBoundary client={qc}>
|
|
17
|
-
* <Comments handle={comments} />
|
|
18
|
-
* </HydrationBoundary>
|
|
19
|
-
* );
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
function HydrationBoundary(props) {
|
|
23
|
-
const client = props.client;
|
|
24
|
-
const state = dehydrate(client, {
|
|
25
|
-
sent: sentHashes(client),
|
|
26
|
-
...props.options
|
|
27
|
-
});
|
|
28
|
-
return /* @__PURE__ */ jsx(Hydrate, {
|
|
29
|
-
state,
|
|
30
|
-
children: props.children
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
//#endregion
|
|
34
|
-
export { HydrationBoundary, QueryProvider };
|