@raf-query/core 0.2.8 → 0.3.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 CHANGED
@@ -1,8 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.1](https://github.com/KATT/raf-query/compare/0.3.0...0.3.1) (2026-10-13)
4
+
5
+ * teach avoiding dependent queries; frame prefetch vs ensure as loading UX ([#62](https://github.com/KATT/raf-query/issues/62)) ([ec62760](https://github.com/KATT/raf-query/commit/ec627609cbbee9fa4ff0cf568f69964341e27daa))
6
+
7
+ ## [0.3.0](https://github.com/KATT/raf-query/compare/0.2.8...0.3.0) (2026-10-13)
8
+
9
+ ### ⚠ BREAKING CHANGES
10
+
11
+ - RSC apps hydrate only through HydrationBoundary; QueryProvider moves to /rsc ([#61](https://github.com/KATT/raf-query/issues/61))
12
+
13
+ ### Features
14
+
15
+ - RSC apps hydrate only through HydrationBoundary; QueryProvider moves to /rsc ([#61](https://github.com/KATT/raf-query/issues/61)) ([772de79](https://github.com/KATT/raf-query/commit/772de796adfdf267a9184fd75624ff30ae53f4fc)), references [#59](https://github.com/KATT/raf-query/issues/59) [#59](https://github.com/KATT/raf-query/issues/59) [#59](https://github.com/KATT/raf-query/issues/59) [#59](https://github.com/KATT/raf-query/issues/59)
16
+
3
17
  ## [0.2.8](https://github.com/KATT/raf-query/compare/0.2.7...0.2.8) (2026-10-13)
4
18
 
5
- * **codesandbox:** speed up the branch sync ([#60](https://github.com/KATT/raf-query/issues/60)) ([9099cb2](https://github.com/KATT/raf-query/commit/9099cb2ce937104d5feb8c7033233e701f412a28))
19
+ - **codesandbox:** speed up the branch sync ([#60](https://github.com/KATT/raf-query/issues/60)) ([9099cb2](https://github.com/KATT/raf-query/commit/9099cb2ce937104d5feb8c7033233e701f412a28))
6
20
 
7
21
  ## [0.2.7](https://github.com/KATT/raf-query/compare/0.2.6...0.2.7) (2026-10-13)
8
22
 
package/README.md CHANGED
@@ -32,12 +32,11 @@ The same issue tracker, built on two frameworks so the integrations can be compa
32
32
 
33
33
  `@raf-query/react` subpath entries for framework integrations and tooling:
34
34
 
35
- | Entry | Use |
36
- | ---------------------------------- | ---------------------------------------------------------------------- |
37
- | `@raf-query/react/tanstack-router` | Streams the router's query cache to the client during SSR |
38
- | `@raf-query/react/rsc` | `HydrationBoundary` for passing server-component queries to the client |
39
- | `@raf-query/react/next` | `QueryProvider` for Next.js App Router |
40
- | `@raf-query/react/devtools` | [Devtools](#devtools) panel for inspecting the cache in development |
35
+ | Entry | Use |
36
+ | ---------------------------------- | ------------------------------------------------------------------- |
37
+ | `@raf-query/react/tanstack-router` | Streams the router's query cache to the client during SSR |
38
+ | `@raf-query/react/rsc` | `QueryProvider` and `HydrationBoundary` for React Server Components |
39
+ | `@raf-query/react/devtools` | [Devtools](#devtools) panel for inspecting the cache in development |
41
40
 
42
41
  ## Principles
43
42
 
@@ -125,7 +124,7 @@ All three verbs live on the query client and accept a factory plus its input.
125
124
  | --------------------------------- | ----------------------------- | ------- | ---------------------------------------------------------------------- |
126
125
  | `qc.prefetch(factory, input)` | `QueryHandle` | No | Data the route can render without; it streams in |
127
126
  | `await qc.ensure(factory, input)` | `Promise<EnsuredQueryHandle>` | Yes | Data the route must not render without; `useQuery` returns it directly |
128
- | `await qc.fetch(factory, input)` | `Promise<Data>` | Yes | Rendering in a server component, or building another input |
127
+ | `await qc.fetch(factory, input)` | `Promise<Data>` | Yes | Rendering data in a server component |
129
128
 
130
129
  ```tsx
131
130
  // TanStack Start
@@ -140,6 +139,13 @@ export const Route = createFileRoute("/posts/$slug")({
140
139
  });
141
140
  ```
142
141
 
142
+ `prefetch` and `ensure` start the request at the same moment, so neither is faster. They differ in what the user sees while it's in flight:
143
+
144
+ - **`prefetch`: granular skeletons.** The navigation commits right away. Each part of the page that reads a query still loading suspends to its nearest Suspense boundary and fills in when its data streams in.
145
+ - **`ensure`: a blocked navigation.** The previous page stays on screen until the data is in. In TanStack Router, a route with a `pendingComponent` shows it once `pendingMs` (1 second by default) has passed, which makes a full-page skeleton.
146
+
147
+ Choose per query. `ensure` what the page can't lay out without, where a skeleton would only flash or shift (the post itself), and `prefetch` the rest (comments, sidebars, counts). Start every query before awaiting any of them, as the `prefetch` before the `await` above does, so a blocking query never delays the others.
148
+
143
149
  Await independent blocking queries together with `allKeyed`, which ships with raf-query. It's a ponyfill of the TC39 `Promise.allKeyed` proposal: a record of promises in, a promise of the same record out, rejecting on the first failure.
144
150
 
145
151
  ```ts
@@ -151,13 +157,74 @@ return await allKeyed({
151
157
  });
152
158
  ```
153
159
 
154
- Dependent inputs use `fetch`:
160
+ ### Avoid dependent queries
161
+
162
+ A query whose input comes from another query's result can't start until that one has finished. That's a waterfall: one extra round trip per level, on every navigation. Fix it where the data is shaped, so every query a route needs starts from what the URL already holds:
163
+
164
+ - **Put the input in the route.** If the page is about an organization, its id belongs in the path (`/orgs/$orgId`), not in a lookup on the current user.
165
+ - **Have the backend resolve it.** The server already knows the session and the relations, so an endpoint can return the child with its parent, or be keyed by what the client has (`GET /me/org` instead of `GET /me` then `GET /orgs/:id`).
166
+
167
+ <details>
168
+ <summary>Example: the current user's organization</summary>
169
+
170
+ A settings page needs the user and their organization, and the organization's id is a field of the user:
155
171
 
156
172
  ```ts
157
- const user = await qc.fetch(currentUserQuery);
158
- return { org: qc.prefetch(orgQuery, { orgId: user.orgId }) };
173
+ export const Route = createFileRoute("/settings")({
174
+ loader: async (args) => {
175
+ const qc = args.context.queryClient;
176
+ const user = await qc.fetch(currentUserQuery);
177
+ return {
178
+ user: qc.prefetch(currentUserQuery),
179
+ org: qc.prefetch(orgQuery, { orgId: user.orgId }),
180
+ };
181
+ },
182
+ });
159
183
  ```
160
184
 
185
+ With a 150 ms round trip, the organization can't arrive before 300 ms, and the navigation is blocked for the first 150 even though nothing on the page needed the user that early. Each query keyed by the organization (members, billing) would add another 150.
186
+
187
+ Fix it in the backend: the server can find the session's organization itself, so give it an endpoint and a query with no input.
188
+
189
+ ```ts
190
+ export function currentOrgQuery() {
191
+ return queryOptions({
192
+ queryKey: ["org", "current"],
193
+ queryFn: () => getCurrentOrg(),
194
+ });
195
+ }
196
+
197
+ export const Route = createFileRoute("/settings")({
198
+ loader: (args) => {
199
+ const qc = args.context.queryClient;
200
+ return {
201
+ user: qc.prefetch(currentUserQuery),
202
+ org: qc.prefetch(currentOrgQuery),
203
+ };
204
+ },
205
+ });
206
+ ```
207
+
208
+ Or fix it in the routes: links into the page come from places that already know the organization (the org switcher, a list of orgs), so they can put its id in the URL.
209
+
210
+ ```ts
211
+ export const Route = createFileRoute("/orgs/$orgId/settings")({
212
+ loader: (args) => {
213
+ const qc = args.context.queryClient;
214
+ return {
215
+ user: qc.prefetch(currentUserQuery),
216
+ org: qc.prefetch(orgQuery, { orgId: args.params.orgId }),
217
+ };
218
+ },
219
+ });
220
+ ```
221
+
222
+ Either way, both requests start together, and the page is ready after one round trip instead of two. Nothing waits, so each query can be a `prefetch` or an `ensure` purely for the loading experience you want.
223
+
224
+ </details>
225
+
226
+ When the data really can't be reshaped (a third-party API you don't control), the loader can `await qc.fetch(...)` the parent and build the input from its data, or a component can start the child with [`useWaterfall`](#render-time-inputs-usewaterfall). Both pay the extra round trip; the loader blocks the navigation on it, the component lets the rest of the page render first.
227
+
161
228
  Behavior:
162
229
 
163
230
  - Every verb dedupes against the cache. A fresh entry is reused; a stale entry is refetched in the background.
@@ -435,7 +502,7 @@ Like `prefetch` in a loader, `useWaterfall` refetches stale cached data in the b
435
502
 
436
503
  The name is the warning: each waterfall is an extra round trip after render. First try to get the input from route params so the loader can start it, or have the backend return it with its parent.
437
504
 
438
- During SSR the `queryFn` runs on the server. TanStack Start server functions work there. Next.js rejects server actions called while rendering, so in Next.js start the dependent query in the server component instead:
505
+ In TanStack Start the `queryFn` runs on the server during SSR, and the router streams the result. Under the `/rsc` `QueryProvider` it starts nothing on the server: the reader's Suspense boundary renders its fallback there, and the query loads in the browser. To have it in the HTML, start the dependent query in the server component instead:
439
506
 
440
507
  ```tsx
441
508
  const post = await qc.fetch(postQuery, { slug });
@@ -518,7 +585,7 @@ export function getRouter() {
518
585
 
519
586
  `setupRouterIntegration` streams queries during SSR, clears the request's cache when the response finishes, and turns `redirect()` thrown from a `queryFn` into a router navigation. `getRouter` runs per request on the server, so each request gets its own client. Options: `dehydrateOptions` (`filter`, `keepErrors`, `serializeData`), `hydrateOptions` (`deserializeData`), and `handleRedirects: false` to handle redirects yourself. By default a server error crosses to the browser as a `RedactedError` naming the query, so its message doesn't leak into the page.
520
587
 
521
- ### Next.js App Router
588
+ ### React Server Components (Next.js App Router)
522
589
 
523
590
  ```tsx
524
591
  // app/get-query-client.ts
@@ -530,7 +597,7 @@ export const getQueryClient = cache(() => new QueryClient());
530
597
 
531
598
  ```tsx
532
599
  // app/layout.tsx
533
- import { QueryProvider } from "@raf-query/react/next";
600
+ import { QueryProvider } from "@raf-query/react/rsc";
534
601
 
535
602
  export default function RootLayout(props: { children: React.ReactNode }) {
536
603
  return (
@@ -570,8 +637,9 @@ export default async function Page(props: {
570
637
  ```
571
638
 
572
639
  - `getQueryClient` is scoped to one request by React's `cache()`.
573
- - `HydrationBoundary` sends the request client's entries to the browser cache; pending ones stream as promises. Render one in each server component that starts queries for client components. Entries already sent in this request are skipped. The browser takes the server's data when it's newer than its own. Otherwise it keeps its copy and refetches it if stale. That covers a payload the router replays from its cache (back and forward) and a `prefetch` still pending on the server.
574
- - `QueryProvider` creates the browser client, and streams queries that client components start during SSR (`useWaterfall`) into the HTML. Pass `config` for the client's options; it must be serializable.
640
+ - `HydrationBoundary` sends the request client's entries to the browser cache; pending ones stream as promises through the RSC payload. Render one in each server component that starts queries for client components. Entries already sent in this request are skipped.
641
+ - The browser takes whichever copy is newer, by when it was fetched (`updatedAt`, so server and browser clocks should agree). When it has no data and no request of its own, it resumes the server's pending request. When it has data, or its own request in flight, it waits for the server's instead of fetching again, and takes it if newer. If it keeps its own copy (the server's is older, as in a payload the router replays from its cache on back and forward, or the server's request failed), it refetches it if stale.
642
+ - `QueryProvider` creates one client per server render and one per browser tab. The server render starts no request: a client component reading a query no `HydrationBoundary` sent renders its Suspense fallback on the server, and the query loads in the browser. That boundary renders in the browser through React's error recovery, with the digest Next.js uses for `ssr: false`, so Next.js doesn't report it; other frameworks pass it to `onRecoverableError`. Pass `config` for the client's options; it must be serializable.
575
643
  - Server components that only render data can `await qc.fetch(...)` anywhere; the per-request client makes one request per query, whatever its `staleTime`.
576
644
  - `fetch` returns data, not a handle. When a server component renders the data and also hands the query to a client component, pass `await qc.ensure(...)`: after the `fetch` it resolves from the cache, and the client component gets the data from `useQuery` without a promise.
577
645
  - Factories can call server actions: server components call them directly, and the browser calls them on refetch. Validate their arguments, since anyone can call them. The browser runs a page's server actions one at a time, so refetches wait for each other and for any pending mutation. For parallel requests, have the `queryFn` call a [Route Handler](https://nextjs.org/docs/app/api-reference/file-conventions/route), as [`examples/nextjs`](examples/nextjs) does.
package/dist/entry.d.mts CHANGED
@@ -122,8 +122,14 @@ export declare function invalidate(entry: Entry): Effect.Effect<void>;
122
122
  export declare function reset(entry: Entry): Effect.Effect<void>;
123
123
  /** Write data directly, as if a request had returned it. */
124
124
  export declare function setData(entry: Entry, data: unknown, updatedAt?: number): void;
125
- /** Adopt a request started elsewhere (the server's, during hydration). */
126
- export declare function resume(entry: Entry, promise: PromiseLike<unknown>): void;
125
+ /**
126
+ * Adopt a request started elsewhere (the server's, during hydration). Its
127
+ * data counts as fetched when the sender got it, not when it arrived.
128
+ */
129
+ export declare function resume(entry: Entry, promise: PromiseLike<{
130
+ readonly data?: unknown;
131
+ readonly updatedAt: number;
132
+ }>): void;
127
133
  /** Refetch a read, stale entry whose readers want it on this event. */
128
134
  export declare function onPlatformEvent(entry: Entry, event: PlatformEvent): void;
129
135
  /** Take `entry` out of its cache: interrupt its fibers and fail its awaiters. */
package/dist/entry.mjs CHANGED
@@ -235,10 +235,18 @@ function reset(entry) {
235
235
  function setData(entry, data, updatedAt = now(entry)) {
236
236
  succeed(entry, data, updatedAt);
237
237
  }
238
- /** Adopt a request started elsewhere (the server's, during hydration). */
238
+ /**
239
+ * Adopt a request started elsewhere (the server's, during hydration). Its
240
+ * data counts as fetched when the sender got it, not when it arrived.
241
+ */
239
242
  function resume(entry, promise) {
240
243
  if (entry.state.hasData || entry.inFlight) return;
241
- startRequest(entry, Effect.promise(() => Promise.resolve(promise)), void 0);
244
+ let updatedAt;
245
+ startRequest(entry, Effect.promise(async () => {
246
+ const result = await promise;
247
+ updatedAt = result.updatedAt;
248
+ return result.data;
249
+ }), void 0, () => updatedAt);
242
250
  }
243
251
  /** Refetch a read, stale entry whose readers want it on this event. */
244
252
  function onPlatformEvent(entry, event) {
@@ -293,7 +301,7 @@ function set(entry, patch) {
293
301
  scheduleStale(entry);
294
302
  }
295
303
  /** Run `request` as the entry's request fiber, settling into its awaiter. */
296
- function startRequest(entry, request, direction) {
304
+ function startRequest(entry, request, direction, updatedAt) {
297
305
  if (!entry.inFlight) entry.failureCountBefore = entry.state.failureCount;
298
306
  const awaiter = entry.inFlight ?? Deferred.makeUnsafe();
299
307
  entry.inFlight = awaiter;
@@ -315,14 +323,14 @@ function startRequest(entry, request, direction) {
315
323
  fetchDirection: direction,
316
324
  isFetching: true
317
325
  });
318
- entry.tasks.fork("request", Effect.exit(request).pipe(Effect.flatMap((exit) => Effect.sync(() => settle(entry, awaiter, exit)))));
326
+ entry.tasks.fork("request", Effect.exit(request).pipe(Effect.flatMap((exit) => Effect.sync(() => settle(entry, awaiter, exit, updatedAt?.() ?? now(entry))))));
319
327
  return awaiter;
320
328
  }
321
- function settle(entry, awaiter, exit) {
329
+ function settle(entry, awaiter, exit, updatedAt) {
322
330
  if (entry.inFlight !== awaiter) return;
323
331
  entry.inFlight = void 0;
324
332
  if (Exit.isSuccess(exit)) {
325
- const data = succeed(entry, exit.value, now(entry));
333
+ const data = succeed(entry, exit.value, updatedAt);
326
334
  Deferred.doneUnsafe(awaiter, Exit.succeed(data));
327
335
  } else if (Cause.hasInterruptsOnly(exit.cause)) {
328
336
  set(entry, {
@@ -366,13 +374,14 @@ function succeed(entry, next, updatedAt) {
366
374
  entry.pending = void 0;
367
375
  firstLoad?.resolve(data);
368
376
  const unchanged = previous.hasData && data === previous.data;
377
+ const isFetching = entry.inFlight !== void 0;
369
378
  set(entry, {
370
379
  data,
371
380
  error: null,
372
381
  failureCount: 0,
373
- fetchDirection: void 0,
382
+ fetchDirection: isFetching ? previous.fetchDirection : void 0,
374
383
  hasData: true,
375
- isFetching: false,
384
+ isFetching,
376
385
  isInvalidated: false,
377
386
  promise: firstLoad?.promise ?? (unchanged ? previous.promise : fulfilled(data)),
378
387
  status: "success",
@@ -5,6 +5,12 @@ import "./entry.mjs";
5
5
  import { Query, query_d_exports } from "./query.mjs";
6
6
  import { Cause, Effect, Scope, Stream } from "effect";
7
7
  //#region src/hydration.d.ts
8
+ /** What a dehydrated pending query's promise resolves to. */
9
+ export interface DehydratedResult {
10
+ readonly data?: unknown;
11
+ /** When the sender got `data` (ms since epoch). */
12
+ readonly updatedAt: number;
13
+ }
8
14
  /**
9
15
  * One cache entry in transit. Settled entries carry `data`; entries still
10
16
  * loading their first data carry the request's `promise`, so the receiving
@@ -15,7 +21,7 @@ export interface DehydratedQuery {
15
21
  readonly key: QueryKey;
16
22
  /** The query's `meta`, for receivers that haven't called its factory. */
17
23
  readonly meta?: QueryMeta;
18
- readonly promise?: Promise<unknown>;
24
+ readonly promise?: Promise<DehydratedResult>;
19
25
  /** When `data` was fetched; `0` while pending. */
20
26
  readonly updatedAt: number;
21
27
  }
@@ -31,7 +31,10 @@ function dehydrateUnsafe(query, options) {
31
31
  data: serialize(state.data),
32
32
  updatedAt: state.updatedAt
33
33
  };
34
- const promise = state.promise.then(serialize, (error) => {
34
+ const promise = state.promise.then((data) => ({
35
+ data: serialize(data),
36
+ updatedAt: getUnsafe(query).updatedAt
37
+ }), (error) => {
35
38
  throw options.keepErrors ? error : new RedactedError({ hash: query.hash });
36
39
  });
37
40
  promise.catch(noop);
@@ -99,23 +102,36 @@ const dehydrateStream = /*#__PURE__*/ Effect.fnUntraced(function* (queries, subs
99
102
  };
100
103
  });
101
104
  /**
105
+ * Take the sender's data if it's newer than the entry's. An entry that keeps
106
+ * its own (the sender's is older, as in a router's cached payload) was asked
107
+ * for again, so it revalidates if stale, as `prefetch` would.
108
+ */
109
+ function takeNewer(entry, data, updatedAt) {
110
+ const current = entry.state;
111
+ if (!current.hasData || current.updatedAt < updatedAt) setData(entry, data, updatedAt);
112
+ else revalidate(entry);
113
+ }
114
+ /**
102
115
  * Write dehydrated entries into a cache. Existing entries only take newer
103
- * data; pending entries resume the sender's request. An entry that keeps its
104
- * own data (the sender's is older, as in a router's cached payload, or still
105
- * pending) was asked for again, so it revalidates if stale, as `prefetch`
106
- * would.
116
+ * data. A pending entry the cache has nothing for resumes the sender's
117
+ * request. One that has data, or a request of its own, waits for the
118
+ * sender's instead of fetching again, and then takes whichever is newer;
119
+ * if the sender's failed, it revalidates.
107
120
  */
108
121
  function hydrateEntries(entryFor, state, options) {
109
122
  const deserialize = options.deserializeData ?? identity;
110
123
  for (const query of state.queries) {
111
124
  const entry = entryFor(query.key);
112
125
  if (!entry.options && query.meta !== void 0) entry.hydratedMeta = query.meta;
113
- const current = entry.state;
114
- if (query.updatedAt > 0) {
115
- if (!current.hasData || current.updatedAt < query.updatedAt) setData(entry, deserialize(query.data), query.updatedAt);
116
- else revalidate(entry);
117
- } else if (query.promise && !current.hasData) resume(entry, Promise.resolve(query.promise).then(deserialize));
118
- else revalidate(entry);
126
+ if (query.updatedAt > 0) takeNewer(entry, deserialize(query.data), query.updatedAt);
127
+ else if (query.promise) {
128
+ const result = Promise.resolve(query.promise).then((sent) => ({
129
+ data: deserialize(sent.data),
130
+ updatedAt: sent.updatedAt
131
+ }));
132
+ if (!entry.state.hasData && !entry.inFlight) resume(entry, result);
133
+ else result.then((sent) => takeNewer(entry, sent.data, sent.updatedAt), () => revalidate(entry));
134
+ } else revalidate(entry);
119
135
  }
120
136
  }
121
137
  //#endregion
package/dist/index.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { platform_d_exports } from "./platform.mjs";
2
2
  import { QueryKey, hashKey, matchesKey } from "./key.mjs";
3
3
  import { AnyQueryOptions, DataOf, EnsuredQueryHandle, ErrorOf, InfiniteData, InfiniteQueryOptions, InputArgs, InputOf, IsPaged, LoadOptions, PageFunctionContext, PageOf, QueryBehavior, QueryFactory, QueryFnResult, QueryFunctionContext, QueryHandle, QueryMeta, QueryOptions, Register, RetryPolicy, ServicesOf, infiniteQueryOptions, queryOptions } from "./options.mjs";
4
- import { DehydrateOptions, DehydratedQuery, DehydratedState, DehydratedStream, HydrateOptions, RedactedError, canDehydrate, dehydrateQuery } from "./hydration.mjs";
4
+ import { DehydrateOptions, DehydratedQuery, DehydratedResult, DehydratedState, DehydratedStream, HydrateOptions, RedactedError, canDehydrate, dehydrateQuery } from "./hydration.mjs";
5
5
  import { cache_d_exports } from "./cache.mjs";
6
6
  import { Thenable } from "./thenable.mjs";
7
7
  import { query_d_exports } from "./query.mjs";
8
8
  import { observer_d_exports } from "./observer.mjs";
9
- export { type AnyQueryOptions, type DataOf, type DehydrateOptions, type DehydratedQuery, type DehydratedState, type DehydratedStream, type EnsuredQueryHandle, type ErrorOf, type HydrateOptions, type InfiniteData, type InfiniteQueryOptions, type InputArgs, type InputOf, type IsPaged, type LoadOptions, type PageFunctionContext, type PageOf, platform_d_exports as Platform, query_d_exports as Query, type QueryBehavior, cache_d_exports as QueryCache, type QueryFactory, type QueryFnResult, type QueryFunctionContext, type QueryHandle, type QueryKey, type QueryMeta, observer_d_exports as QueryObserver, type QueryOptions, RedactedError, type Register, type RetryPolicy, type ServicesOf, type Thenable, canDehydrate, dehydrateQuery, hashKey, infiniteQueryOptions, matchesKey, queryOptions };
9
+ export { type AnyQueryOptions, type DataOf, type DehydrateOptions, type DehydratedQuery, type DehydratedResult, type DehydratedState, type DehydratedStream, type EnsuredQueryHandle, type ErrorOf, type HydrateOptions, type InfiniteData, type InfiniteQueryOptions, type InputArgs, type InputOf, type IsPaged, type LoadOptions, type PageFunctionContext, type PageOf, platform_d_exports as Platform, query_d_exports as Query, type QueryBehavior, cache_d_exports as QueryCache, type QueryFactory, type QueryFnResult, type QueryFunctionContext, type QueryHandle, type QueryKey, type QueryMeta, observer_d_exports as QueryObserver, type QueryOptions, RedactedError, type Register, type RetryPolicy, type ServicesOf, type Thenable, canDehydrate, dehydrateQuery, hashKey, infiniteQueryOptions, matchesKey, queryOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/core",
3
- "version": "0.2.8",
3
+ "version": "0.3.1",
4
4
  "description": "Framework-agnostic core of raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",