@raf-query/core 0.10.3 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -1
- package/dist/client.d.mts +2 -1
- package/dist/controls.d.mts +8 -0
- package/dist/controls.mjs +11 -1
- package/dist/entry.d.mts +14 -8
- package/dist/entry.mjs +22 -18
- package/dist/hydration.d.mts +2 -0
- package/dist/hydration.mjs +13 -3
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/infinite.mjs +34 -3
- package/dist/options.d.mts +14 -9
- package/dist/query.d.mts +11 -4
- package/dist/query.mjs +14 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.0](https://github.com/KATT/raf-query/compare/0.10.4...0.11.0) (2026-10-16)
|
|
4
|
+
|
|
5
|
+
### ⚠ BREAKING CHANGES
|
|
6
|
+
|
|
7
|
+
* **core:** enabled replaces ssr, as a boolean like TanStack Query's ([#204](https://github.com/KATT/raf-query/issues/204))
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **core:** enabled replaces ssr, as a boolean like TanStack Query's ([#204](https://github.com/KATT/raf-query/issues/204)) ([b7e543b](https://github.com/KATT/raf-query/commit/b7e543b9d1d34e02061740f749f2ddabcdee2ad2))
|
|
12
|
+
|
|
13
|
+
## [0.10.4](https://github.com/KATT/raf-query/compare/0.10.3...0.10.4) (2026-10-16)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- **core:** keep pages written during a paged refetch ([#215](https://github.com/KATT/raf-query/issues/215)) ([b6a5946](https://github.com/KATT/raf-query/commit/b6a5946e806e12e9b7df40e80ef0e532c0871b25)), references [#75](https://github.com/KATT/raf-query/issues/75)
|
|
18
|
+
- **react:** read promise queryFns as plain data on a client with a layer (1/2) ([#205](https://github.com/KATT/raf-query/issues/205)) ([a9b156e](https://github.com/KATT/raf-query/commit/a9b156edfa18b1e41e9ea929afc412252a61b83c))
|
|
19
|
+
|
|
3
20
|
## [0.10.3](https://github.com/KATT/raf-query/compare/0.10.2...0.10.3) (2026-10-16)
|
|
4
21
|
|
|
5
22
|
### Features
|
|
6
23
|
|
|
7
|
-
|
|
24
|
+
- **core:** add QueryBinding, a framework-free useQuery for bindings ([#197](https://github.com/KATT/raf-query/issues/197)) ([4865802](https://github.com/KATT/raf-query/commit/48658024f4d21d43ce8274de379a19c8898b6173)), references [#194](https://github.com/KATT/raf-query/issues/194)
|
|
8
25
|
|
|
9
26
|
## [0.10.2](https://github.com/KATT/raf-query/compare/0.10.1...0.10.2) (2026-10-16)
|
|
10
27
|
|
package/dist/client.d.mts
CHANGED
|
@@ -17,7 +17,8 @@ export interface QueryClientConfig<TServices = never> extends Config {
|
|
|
17
17
|
* When `false`, `useQuery` for an Effect `queryFn` (a typed `ErrorOf`)
|
|
18
18
|
* returns a `Result` in the first tuple slot instead of a promise that
|
|
19
19
|
* rejects. Defaults to `false` when `layer` is set, `true` otherwise.
|
|
20
|
-
* Promise `queryFn`s always throw
|
|
20
|
+
* Promise `queryFn`s always throw, whatever this flag says: reads tell
|
|
21
|
+
* them apart by what the `queryFn` returned ({@link Query.returnsEffectUnsafe}).
|
|
21
22
|
*/
|
|
22
23
|
readonly throwOnError?: boolean;
|
|
23
24
|
}
|
package/dist/controls.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryKey } from "./key.mjs";
|
|
2
2
|
import { DataOf, ErrorOf, InputOf, IsPaged, QueryFactory } from "./options.mjs";
|
|
3
3
|
import { Thenable } from "./thenable.mjs";
|
|
4
|
+
import { Query, query_d_exports } from "./query.mjs";
|
|
4
5
|
import { Options, Result as Result$1, observer_d_exports } from "./observer.mjs";
|
|
5
6
|
import { Result } from "effect";
|
|
6
7
|
//#region src/controls.d.ts
|
|
@@ -65,6 +66,13 @@ export type HasTypedError<TFactory extends QueryFactory> = unknown extends Error
|
|
|
65
66
|
* (Result), matching a client with a `layer`.
|
|
66
67
|
*/
|
|
67
68
|
export type ThrowsOnError<TFactory extends QueryFactory, TThrow extends boolean | undefined> = HasTypedError<TFactory> extends false ? true : TThrow extends boolean ? TThrow : false;
|
|
69
|
+
/**
|
|
70
|
+
* {@link ThrowsOnError} at runtime, for bindings: a read of `query` throws
|
|
71
|
+
* when `throwOnError` (the call's, else the client's) is `true`, or when its
|
|
72
|
+
* `queryFn` returns a promise or plain value, whose error isn't typed. A
|
|
73
|
+
* query whose `queryFn` hasn't run yet follows `throwOnError`.
|
|
74
|
+
*/
|
|
75
|
+
export declare function throwsOnError<TFactory extends QueryFactory>(query: Query<TFactory>, throwOnError: boolean): boolean;
|
|
68
76
|
/** What a read settles with: the data, or a `Result` when it doesn't throw. */
|
|
69
77
|
export type ReadValue<TFactory extends QueryFactory, TThrow extends boolean | undefined = undefined> = ThrowsOnError<TFactory, TThrow> extends true ? DataOf<TFactory> : Result.Result<DataOf<TFactory>, ErrorOf<TFactory>>;
|
|
70
78
|
type Command = "fetchNextPage" | "fetchPreviousPage" | "refetch";
|
package/dist/controls.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fulfilled, pending } from "./thenable.mjs";
|
|
2
|
+
import { returnsEffectUnsafe } from "./query.mjs";
|
|
2
3
|
import { Effect, Result } from "effect";
|
|
3
4
|
//#region src/controls.ts
|
|
4
5
|
/**
|
|
@@ -6,6 +7,15 @@ import { Effect, Result } from "effect";
|
|
|
6
7
|
* observer's result with Promise commands, and the types every binding
|
|
7
8
|
* shares. The React, Svelte and Vue packages build their reads on this.
|
|
8
9
|
*/
|
|
10
|
+
/**
|
|
11
|
+
* {@link ThrowsOnError} at runtime, for bindings: a read of `query` throws
|
|
12
|
+
* when `throwOnError` (the call's, else the client's) is `true`, or when its
|
|
13
|
+
* `queryFn` returns a promise or plain value, whose error isn't typed. A
|
|
14
|
+
* query whose `queryFn` hasn't run yet follows `throwOnError`.
|
|
15
|
+
*/
|
|
16
|
+
function throwsOnError(query, throwOnError) {
|
|
17
|
+
return throwOnError || returnsEffectUnsafe(query) === false;
|
|
18
|
+
}
|
|
9
19
|
const commands = /* @__PURE__ */ new WeakMap();
|
|
10
20
|
/** One stable Promise function per command Effect, so identities track the query's. */
|
|
11
21
|
function commandFor(effect) {
|
|
@@ -56,4 +66,4 @@ function resultThenable(promise) {
|
|
|
56
66
|
return next;
|
|
57
67
|
}
|
|
58
68
|
//#endregion
|
|
59
|
-
export { promiseControls, resultThenable };
|
|
69
|
+
export { promiseControls, resultThenable, throwsOnError };
|
package/dist/entry.d.mts
CHANGED
|
@@ -6,7 +6,7 @@ import { FetchRequest, Query, State, SubscribeOptions } from "./query.mjs";
|
|
|
6
6
|
import { Event } from "./cache.mjs";
|
|
7
7
|
import { Cause, Clock, Context, Deferred, Effect, Scope, Stream } from "effect";
|
|
8
8
|
declare namespace entry_d_exports {
|
|
9
|
-
export {
|
|
9
|
+
export { CacheState, CancelledError, DisabledError, Entry, TypeId, changes, emit, entryOf, fetch, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isDisabled, isObserved, isQuery, isStaleUnsafe, make, metaOf, needsRefetch, onPlatformEvent, provide, readUnsafe, remove, reset, resume, revalidate, setData, setOptions, start, subscribeUnsafe };
|
|
10
10
|
}
|
|
11
11
|
export declare const TypeId = "~@raf-query/core/Query";
|
|
12
12
|
declare const CancelledError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
|
|
@@ -19,14 +19,14 @@ declare const CancelledError_base: new <A extends Record<string, any> = {}>(args
|
|
|
19
19
|
export declare class CancelledError extends CancelledError_base {
|
|
20
20
|
readonly message = "The query was cancelled";
|
|
21
21
|
}
|
|
22
|
-
declare const
|
|
23
|
-
readonly _tag: "
|
|
22
|
+
declare const DisabledError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => Cause.YieldableError & {
|
|
23
|
+
readonly _tag: "DisabledError";
|
|
24
24
|
} & Readonly<A>;
|
|
25
25
|
/**
|
|
26
|
-
* Why a query with `
|
|
27
|
-
*
|
|
26
|
+
* Why a query with `enabled: false` has no data: `ensure` / `fetch` die
|
|
27
|
+
* with it, and on a server its promise rejects with it.
|
|
28
28
|
*/
|
|
29
|
-
export declare class
|
|
29
|
+
export declare class DisabledError extends DisabledError_base<{
|
|
30
30
|
readonly hash: string;
|
|
31
31
|
}> {
|
|
32
32
|
get message(): string;
|
|
@@ -79,6 +79,12 @@ export interface Entry extends Query {
|
|
|
79
79
|
pending: Pending<unknown> | undefined;
|
|
80
80
|
/** The last reader left during the request in flight: it retries no more. */
|
|
81
81
|
retriesStopped: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* The last `queryFn` call returned an Effect (`true`) or a promise or
|
|
84
|
+
* plain value (`false`), here or on the cache it was hydrated from.
|
|
85
|
+
* `undefined` until one has run.
|
|
86
|
+
*/
|
|
87
|
+
returnsEffect: boolean | undefined;
|
|
82
88
|
/** Open while the entry is cached; owns its fibers. */
|
|
83
89
|
readonly scope: Scope.Closeable;
|
|
84
90
|
/**
|
|
@@ -100,8 +106,8 @@ export declare function emit(cache: CacheState, event: Event): void;
|
|
|
100
106
|
export declare function make(cache: CacheState, key: QueryKey, hash: string): Entry;
|
|
101
107
|
/** Readers are subscribed; `invalidate` and focus refetch only what is read. */
|
|
102
108
|
export declare function isObserved(entry: Entry): boolean;
|
|
103
|
-
/**
|
|
104
|
-
export declare function
|
|
109
|
+
/** The entry's latest factory call returned `enabled: false`: it doesn't run. */
|
|
110
|
+
export declare function isDisabled(entry: Entry): boolean;
|
|
105
111
|
/** Until a factory call attaches options, `meta` comes from hydration. */
|
|
106
112
|
export declare function metaOf(entry: Entry): QueryMeta | undefined;
|
|
107
113
|
export declare function isStaleUnsafe(entry: Entry): boolean;
|
package/dist/entry.mjs
CHANGED
|
@@ -17,12 +17,12 @@ var CancelledError = class extends Data.TaggedError("CancelledError") {
|
|
|
17
17
|
message = "The query was cancelled";
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
|
-
* Why a query with `
|
|
21
|
-
*
|
|
20
|
+
* Why a query with `enabled: false` has no data: `ensure` / `fetch` die
|
|
21
|
+
* with it, and on a server its promise rejects with it.
|
|
22
22
|
*/
|
|
23
|
-
var
|
|
23
|
+
var DisabledError = class extends Data.TaggedError("DisabledError") {
|
|
24
24
|
get message() {
|
|
25
|
-
return `Query ${this.hash}
|
|
25
|
+
return `Query ${this.hash} is disabled (enabled: false)`;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const Proto = {
|
|
@@ -76,6 +76,7 @@ function make(cache, key, hash) {
|
|
|
76
76
|
options: void 0,
|
|
77
77
|
pending: first,
|
|
78
78
|
retriesStopped: false,
|
|
79
|
+
returnsEffect: void 0,
|
|
79
80
|
scope,
|
|
80
81
|
services: cache.services,
|
|
81
82
|
signalRead: false,
|
|
@@ -94,7 +95,7 @@ function make(cache, key, hash) {
|
|
|
94
95
|
},
|
|
95
96
|
tasks: makeTasks(cache, scope)
|
|
96
97
|
});
|
|
97
|
-
const command = (request) => Effect.suspend(() =>
|
|
98
|
+
const command = (request) => Effect.suspend(() => isDisabled(entry) ? Effect.void : Effect.ignore(fetch(entry, request)));
|
|
98
99
|
const commands = {
|
|
99
100
|
fetchNextPage: command({ direction: "forward" }),
|
|
100
101
|
fetchPreviousPage: command({ direction: "backward" }),
|
|
@@ -114,9 +115,9 @@ function isObserved(entry) {
|
|
|
114
115
|
function behavior(entry, name) {
|
|
115
116
|
return entry.options?.[name] ?? entry.cache.defaults[name];
|
|
116
117
|
}
|
|
117
|
-
/**
|
|
118
|
-
function
|
|
119
|
-
return
|
|
118
|
+
/** The entry's latest factory call returned `enabled: false`: it doesn't run. */
|
|
119
|
+
function isDisabled(entry) {
|
|
120
|
+
return behavior(entry, "enabled") === false;
|
|
120
121
|
}
|
|
121
122
|
/** Until a factory call attaches options, `meta` comes from hydration. */
|
|
122
123
|
function metaOf(entry) {
|
|
@@ -224,7 +225,7 @@ function fetch(entry, request = {}) {
|
|
|
224
225
|
function invalidate(entry) {
|
|
225
226
|
return Effect.suspend(() => {
|
|
226
227
|
set(entry, { isInvalidated: true });
|
|
227
|
-
if (!isObserved(entry) || !entry.options ||
|
|
228
|
+
if (!isObserved(entry) || !entry.options || isDisabled(entry)) return Effect.void;
|
|
228
229
|
return Effect.ignore(begin(entry, { restart: true }));
|
|
229
230
|
});
|
|
230
231
|
}
|
|
@@ -243,7 +244,7 @@ function reset(entry) {
|
|
|
243
244
|
status: "pending",
|
|
244
245
|
updatedAt: 0
|
|
245
246
|
});
|
|
246
|
-
if (!entry.options ||
|
|
247
|
+
if (!entry.options || isDisabled(entry) || !isObserved(entry) && !entry.inFlight) return Effect.void;
|
|
247
248
|
return Effect.ignore(begin(entry, { restart: true }));
|
|
248
249
|
});
|
|
249
250
|
}
|
|
@@ -290,11 +291,13 @@ function remove(entry) {
|
|
|
290
291
|
*/
|
|
291
292
|
function begin(entry, request) {
|
|
292
293
|
if (Predicate.isTagged(entry.scope.state, "Closed")) return Effect.fail(new CancelledError());
|
|
293
|
-
if (
|
|
294
|
-
const error = new
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
294
|
+
if (isDisabled(entry)) {
|
|
295
|
+
const error = new DisabledError({ hash: entry.hash });
|
|
296
|
+
if (entry.cache.isServer) {
|
|
297
|
+
const firstLoad = entry.pending;
|
|
298
|
+
entry.pending = void 0;
|
|
299
|
+
firstLoad?.reject(error);
|
|
300
|
+
}
|
|
298
301
|
return Effect.die(error);
|
|
299
302
|
}
|
|
300
303
|
const options = entry.options;
|
|
@@ -331,7 +334,7 @@ function startRequest(entry, request, direction, updatedAt) {
|
|
|
331
334
|
entry.retriesStopped = false;
|
|
332
335
|
entry.signalRead = false;
|
|
333
336
|
entry.tasks.cancel("gc");
|
|
334
|
-
if (!entry.state.hasData && entry.
|
|
337
|
+
if (!entry.state.hasData && !entry.pending) {
|
|
335
338
|
entry.pending = pending();
|
|
336
339
|
set(entry, {
|
|
337
340
|
error: null,
|
|
@@ -475,7 +478,8 @@ function attempt(entry, call) {
|
|
|
475
478
|
entry.signalRead = true;
|
|
476
479
|
return signal;
|
|
477
480
|
});
|
|
478
|
-
|
|
481
|
+
entry.returnsEffect = Effect.isEffect(result);
|
|
482
|
+
if (entry.returnsEffect) entry.signalRead = true;
|
|
479
483
|
return result;
|
|
480
484
|
}).pipe(Effect.tapError(() => Effect.sync(() => set(entry, { failureCount: entry.state.failureCount + 1 }))));
|
|
481
485
|
const schedule = retrySchedule({
|
|
@@ -519,4 +523,4 @@ function scheduleStale(entry) {
|
|
|
519
523
|
entry.tasks.fork("stale", Effect.sleep(Math.max(remaining, 0) + 1).pipe(Effect.andThen(Effect.sync(() => set(entry, {})))));
|
|
520
524
|
}
|
|
521
525
|
//#endregion
|
|
522
|
-
export {
|
|
526
|
+
export { CancelledError, DisabledError, TypeId, changes, emit, entryOf, fetch, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isDisabled, isObserved, isQuery, isStaleUnsafe, make, metaOf, needsRefetch, onPlatformEvent, provide, readUnsafe, remove, reset, resume, revalidate, setData, setOptions, start, subscribeUnsafe };
|
package/dist/hydration.d.mts
CHANGED
|
@@ -18,6 +18,8 @@ export interface DehydratedResult {
|
|
|
18
18
|
*/
|
|
19
19
|
export interface DehydratedQuery {
|
|
20
20
|
readonly data?: unknown;
|
|
21
|
+
/** Whether the sender's `queryFn` returned an Effect, when it ran there. */
|
|
22
|
+
readonly effect?: boolean;
|
|
21
23
|
readonly key: QueryKey;
|
|
22
24
|
/** The query's `meta`, for receivers that haven't called its factory. */
|
|
23
25
|
readonly meta?: QueryMeta;
|
package/dist/hydration.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { entryOf,
|
|
2
|
-
import { getUnsafe, metaUnsafe } from "./query.mjs";
|
|
1
|
+
import { entryOf, isDisabled, resume, revalidate, setData } from "./entry.mjs";
|
|
2
|
+
import { getUnsafe, metaUnsafe, returnsEffectUnsafe } from "./query.mjs";
|
|
3
3
|
import { Data, Effect, Queue, Stream } from "effect";
|
|
4
4
|
//#region src/hydration.ts
|
|
5
5
|
/**
|
|
@@ -19,6 +19,15 @@ function canDehydrate(query) {
|
|
|
19
19
|
return state.hasData || state.isFetching;
|
|
20
20
|
}
|
|
21
21
|
function dehydrateUnsafe(query, options) {
|
|
22
|
+
const sent = dehydrateState(query, options);
|
|
23
|
+
const effect = returnsEffectUnsafe(query);
|
|
24
|
+
return effect === void 0 ? sent : {
|
|
25
|
+
...sent,
|
|
26
|
+
effect
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** {@link dehydrateUnsafe} without `effect`. */
|
|
30
|
+
function dehydrateState(query, options) {
|
|
22
31
|
const state = getUnsafe(query);
|
|
23
32
|
const serialize = options.serializeData ?? identity;
|
|
24
33
|
const meta = metaUnsafe(query);
|
|
@@ -53,7 +62,7 @@ function dehydrateEntries(queries, options) {
|
|
|
53
62
|
const filter = options.filter ?? canDehydrate;
|
|
54
63
|
const sent = options.sent;
|
|
55
64
|
const dehydrated = [];
|
|
56
|
-
for (const query of queries) if (!sent?.has(query.hash) && !
|
|
65
|
+
for (const query of queries) if (!sent?.has(query.hash) && !isDisabled(entryOf(query)) && filter(query)) {
|
|
57
66
|
sent?.add(query.hash);
|
|
58
67
|
dehydrated.push(dehydrateUnsafe(query, options));
|
|
59
68
|
}
|
|
@@ -123,6 +132,7 @@ function hydrateEntries(entryFor, state, options) {
|
|
|
123
132
|
for (const query of state.queries) {
|
|
124
133
|
const entry = entryFor(query.key);
|
|
125
134
|
if (!entry.options && query.meta !== void 0) entry.hydratedMeta = query.meta;
|
|
135
|
+
entry.returnsEffect ??= query.effect;
|
|
126
136
|
if (query.updatedAt > 0) takeNewer(entry, deserialize(query.data), query.updatedAt);
|
|
127
137
|
else if (query.promise) {
|
|
128
138
|
const result = Promise.resolve(query.promise).then((sent) => ({
|
package/dist/index.d.mts
CHANGED
|
@@ -8,6 +8,6 @@ import { DehydrateOptions, DehydratedQuery, DehydratedResult, DehydratedState, D
|
|
|
8
8
|
import { cache_d_exports } from "./cache.mjs";
|
|
9
9
|
import { QueryClient, QueryClientConfig, dehydrate, hydrate } from "./client.mjs";
|
|
10
10
|
import { observer_d_exports } from "./observer.mjs";
|
|
11
|
-
import { HasTypedError, PagingControls, PromiseControls, QueryControls, ReadValue, ThrowsOnError, UseQueryControls, UseQueryOptions, UseQueryThrowOptions, promiseControls, resultThenable } from "./controls.mjs";
|
|
11
|
+
import { HasTypedError, PagingControls, PromiseControls, QueryControls, ReadValue, ThrowsOnError, UseQueryControls, UseQueryOptions, UseQueryThrowOptions, promiseControls, resultThenable, throwsOnError } from "./controls.mjs";
|
|
12
12
|
import { binding_d_exports } from "./binding.mjs";
|
|
13
|
-
export { type AnyQueryOptions, type DataOf, type DehydrateOptions, type DehydratedQuery, type DehydratedResult, type DehydratedState, type DehydratedStream, type ErrorOf, type HasTypedError, type HydrateOptions, type InfiniteData, type InfiniteQueryOptions, type InfiniteQueryTypes, type InputArgs, type InputOf, type IsPaged, type LoadOptions, type PageFunctionContext, type PageOf, type PagedQueryFactory, type PagingControls, type Pending, platform_d_exports as Platform, type PromiseControls, query_d_exports as Query, type QueryBehavior, binding_d_exports as QueryBinding, cache_d_exports as QueryCache, QueryClient, type QueryClientConfig, type QueryControls, type QueryFactory, type QueryFnResult, type QueryFunctionContext, type QueryHandle, type QueryHandleWithData, type QueryKey, type QueryMeta, observer_d_exports as QueryObserver, type QueryOptions, type QueryTypes, type ReadValue, RedactedError, type Register, type RetryPolicy, type ServicesOf, type Settled, type Thenable, type ThrowsOnError, type UseQueryControls, type UseQueryOptions, type UseQueryThrowOptions, allKeyed, canDehydrate, dehydrate, dehydrateQuery, fulfilled, hashKey, hydrate, infiniteQueryOptions, matchesKey, pending, promiseControls, queryOptions, resultThenable };
|
|
13
|
+
export { type AnyQueryOptions, type DataOf, type DehydrateOptions, type DehydratedQuery, type DehydratedResult, type DehydratedState, type DehydratedStream, type ErrorOf, type HasTypedError, type HydrateOptions, type InfiniteData, type InfiniteQueryOptions, type InfiniteQueryTypes, type InputArgs, type InputOf, type IsPaged, type LoadOptions, type PageFunctionContext, type PageOf, type PagedQueryFactory, type PagingControls, type Pending, platform_d_exports as Platform, type PromiseControls, query_d_exports as Query, type QueryBehavior, binding_d_exports as QueryBinding, cache_d_exports as QueryCache, QueryClient, type QueryClientConfig, type QueryControls, type QueryFactory, type QueryFnResult, type QueryFunctionContext, type QueryHandle, type QueryHandleWithData, type QueryKey, type QueryMeta, observer_d_exports as QueryObserver, type QueryOptions, type QueryTypes, type ReadValue, RedactedError, type Register, type RetryPolicy, type ServicesOf, type Settled, type Thenable, type ThrowsOnError, type UseQueryControls, type UseQueryOptions, type UseQueryThrowOptions, allKeyed, canDehydrate, dehydrate, dehydrateQuery, fulfilled, hashKey, hydrate, infiniteQueryOptions, matchesKey, pending, promiseControls, queryOptions, resultThenable, throwsOnError };
|
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { RedactedError, canDehydrate, dehydrateQuery } from "./hydration.mjs";
|
|
|
7
7
|
import { infiniteQueryOptions, queryOptions } from "./options.mjs";
|
|
8
8
|
import { cache_exports } from "./cache.mjs";
|
|
9
9
|
import { QueryClient, dehydrate, hydrate } from "./client.mjs";
|
|
10
|
-
import { promiseControls, resultThenable } from "./controls.mjs";
|
|
10
|
+
import { promiseControls, resultThenable, throwsOnError } from "./controls.mjs";
|
|
11
11
|
import { observer_exports } from "./observer.mjs";
|
|
12
12
|
import { binding_exports } from "./binding.mjs";
|
|
13
|
-
export { platform_exports as Platform, query_exports as Query, binding_exports as QueryBinding, cache_exports as QueryCache, QueryClient, observer_exports as QueryObserver, RedactedError, allKeyed, canDehydrate, dehydrate, dehydrateQuery, fulfilled, hashKey, hydrate, infiniteQueryOptions, matchesKey, pending, promiseControls, queryOptions, resultThenable };
|
|
13
|
+
export { platform_exports as Platform, query_exports as Query, binding_exports as QueryBinding, cache_exports as QueryCache, QueryClient, observer_exports as QueryObserver, RedactedError, allKeyed, canDehydrate, dehydrate, dehydrateQuery, fulfilled, hashKey, hydrate, infiniteQueryOptions, matchesKey, pending, promiseControls, queryOptions, resultThenable, throwsOnError };
|
package/dist/infinite.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { replaceEqualDeep } from "./share.mjs";
|
|
2
|
-
import { Effect, Predicate } from "effect";
|
|
2
|
+
import { Effect, Option, Predicate } from "effect";
|
|
3
3
|
//#region src/infinite.ts
|
|
4
4
|
function isInfiniteData(data) {
|
|
5
5
|
return Predicate.hasProperty(data, "pages") && Predicate.hasProperty(data, "pageParams") && Array.isArray(data.pages) && Array.isArray(data.pageParams);
|
|
@@ -31,6 +31,31 @@ function addPage(data, page, pageParam, direction, maxPages) {
|
|
|
31
31
|
function edgeParam(data, direction) {
|
|
32
32
|
return direction === "forward" ? data.pageParams.at(-1) : data.pageParams[0];
|
|
33
33
|
}
|
|
34
|
+
/** The page `data` holds for `pageParam`, compared deeply. */
|
|
35
|
+
function pageFor(data, pageParam) {
|
|
36
|
+
const index = data?.pageParams.findIndex((param) => replaceEqualDeep(param, pageParam) === param) ?? -1;
|
|
37
|
+
return index === -1 ? Option.none() : Option.some(data?.pages[index]);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* `data`, a full refetch's pages, with each page that `latest` replaced
|
|
41
|
+
* after the refetch started reading it: that write is newer than the read.
|
|
42
|
+
* A page written before its read started is read again, and the read wins.
|
|
43
|
+
*/
|
|
44
|
+
function keepWrites(data, readFrom, latest) {
|
|
45
|
+
let changed = false;
|
|
46
|
+
const pages = data.pages.map((page, index) => {
|
|
47
|
+
const pageParam = data.pageParams[index];
|
|
48
|
+
const read = readFrom.find((entry) => replaceEqualDeep(entry.pageParam, pageParam) === entry.pageParam);
|
|
49
|
+
const now = pageFor(latest, pageParam);
|
|
50
|
+
if (!read || Option.isNone(now) || Option.isSome(read.seen) && read.seen.value === now.value) return page;
|
|
51
|
+
changed = true;
|
|
52
|
+
return now.value;
|
|
53
|
+
});
|
|
54
|
+
return changed ? {
|
|
55
|
+
pageParams: data.pageParams,
|
|
56
|
+
pages
|
|
57
|
+
} : data;
|
|
58
|
+
}
|
|
34
59
|
/**
|
|
35
60
|
* A paged query's request. With a `direction`, adds one page at that end of
|
|
36
61
|
* the entry's data, read again with `latest` once the page loads, so data
|
|
@@ -38,7 +63,8 @@ function edgeParam(data, direction) {
|
|
|
38
63
|
* longer ends at the page param the request started from, the write
|
|
39
64
|
* replaced the list, and the page is dropped. Without a `direction`, loads
|
|
40
65
|
* from the first page param again: as many pages as `current` has, or
|
|
41
|
-
* `pages` if that's more, stopping at the last page.
|
|
66
|
+
* `pages` if that's more, stopping at the last page. A page written while
|
|
67
|
+
* the refetch was reading it, or after, stays as written ({@link keepWrites}).
|
|
42
68
|
*/
|
|
43
69
|
const fetchPages = /*#__PURE__*/ Effect.fnUntraced(function* (options, current, request, fetchPage, latest) {
|
|
44
70
|
const direction = request.direction;
|
|
@@ -56,6 +82,7 @@ const fetchPages = /*#__PURE__*/ Effect.fnUntraced(function* (options, current,
|
|
|
56
82
|
pageParams: [],
|
|
57
83
|
pages: []
|
|
58
84
|
};
|
|
85
|
+
const readFrom = [];
|
|
59
86
|
let pageParam = current && current.pageParams.length > 0 ? current.pageParams[0] : options.initialPageParam;
|
|
60
87
|
for (let index = 0; index < count; index++) {
|
|
61
88
|
if (index > 0) {
|
|
@@ -63,10 +90,14 @@ const fetchPages = /*#__PURE__*/ Effect.fnUntraced(function* (options, current,
|
|
|
63
90
|
if (next == null) break;
|
|
64
91
|
pageParam = next;
|
|
65
92
|
}
|
|
93
|
+
readFrom.push({
|
|
94
|
+
pageParam,
|
|
95
|
+
seen: pageFor(latest(), pageParam)
|
|
96
|
+
});
|
|
66
97
|
const page = yield* fetchPage(pageParam, "forward");
|
|
67
98
|
data = addPage(data, page, pageParam, "forward", options.maxPages);
|
|
68
99
|
}
|
|
69
|
-
return data;
|
|
100
|
+
return keepWrites(data, readFrom, latest());
|
|
70
101
|
});
|
|
71
102
|
//#endregion
|
|
72
103
|
export { fetchPages, isInfiniteData, nextPageParam, previousPageParam };
|
package/dist/options.d.mts
CHANGED
|
@@ -135,6 +135,20 @@ export interface PageFunctionContext<TPageParam> extends QueryFunctionContext {
|
|
|
135
135
|
export type RetryPolicy = boolean | number | Schedule.Schedule<unknown, unknown> | ((failureCount: number, error: unknown) => boolean);
|
|
136
136
|
/** Options every query accepts. `QueryCache` defaults fill in the rest. */
|
|
137
137
|
export interface QueryBehavior {
|
|
138
|
+
/**
|
|
139
|
+
* `false` keeps the query from running. Default `true`. The factory
|
|
140
|
+
* decides per call, so `enabled: typeof window !== "undefined"` runs a
|
|
141
|
+
* query only in the browser, for data only a browser has (permissions,
|
|
142
|
+
* device APIs, `localStorage`).
|
|
143
|
+
*
|
|
144
|
+
* While disabled, readers see `isPending`, `ensure` and `fetch` fail with
|
|
145
|
+
* `Query.DisabledError`, and `invalidate`, `reset` and `refetch` do
|
|
146
|
+
* nothing. In the browser, its promise stays pending until a factory
|
|
147
|
+
* call returns `true` and runs it. A server cache never sends it, and its
|
|
148
|
+
* promise rejects with `Query.DisabledError`: under Suspense, React
|
|
149
|
+
* renders the fallback on the server and the component in the browser.
|
|
150
|
+
*/
|
|
151
|
+
readonly enabled?: boolean;
|
|
138
152
|
/** How long an unread entry stays cached, in ms. `Infinity` keeps it. */
|
|
139
153
|
readonly gcTime?: number;
|
|
140
154
|
/**
|
|
@@ -151,15 +165,6 @@ export interface QueryBehavior {
|
|
|
151
165
|
readonly retry?: RetryPolicy;
|
|
152
166
|
/** Delay before retry number `failureCount` (1-based), in ms. */
|
|
153
167
|
readonly retryDelay?: number | ((failureCount: number, error: unknown) => number);
|
|
154
|
-
/**
|
|
155
|
-
* `false`: only the browser runs the query, for data only a browser has
|
|
156
|
-
* (permissions, device APIs). A server cache never starts it or sends it.
|
|
157
|
-
* Readers there see `isPending`, and a promise that rejects with
|
|
158
|
-
* `Query.BrowserOnlyError`: under Suspense, React renders the fallback on
|
|
159
|
-
* the server and the query in the browser. `ensure` and `fetch` on the
|
|
160
|
-
* server fail with that error. Default `true`.
|
|
161
|
-
*/
|
|
162
|
-
readonly ssr?: boolean;
|
|
163
168
|
/** How long data counts as fresh, in ms. Fresh data is never refetched. */
|
|
164
169
|
readonly staleTime?: number;
|
|
165
170
|
/**
|
package/dist/query.d.mts
CHANGED
|
@@ -2,10 +2,10 @@ import { QueryKey } from "./key.mjs";
|
|
|
2
2
|
import { AnyQueryOptions, DataOf, ErrorOf, QueryFactory, QueryHandle, QueryMeta, ServicesOf } from "./options.mjs";
|
|
3
3
|
import { Direction } from "./infinite.mjs";
|
|
4
4
|
import { Thenable } from "./thenable.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { CancelledError as CancelledError$1, DisabledError as DisabledError$1, TypeId as TypeId$1, entry_d_exports } from "./entry.mjs";
|
|
6
6
|
import { Effect, Pipeable, Stream } from "effect";
|
|
7
7
|
declare namespace query_d_exports {
|
|
8
|
-
export {
|
|
8
|
+
export { CancelledError, DisabledError, FetchRequest, Query, State, SubscribeOptions, TypeId, changes, fetch, fetchNextPage, fetchPreviousPage, get, getUnsafe, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isQuery, isStaleUnsafe, metaUnsafe, observerCountUnsafe, readUnsafe, refetch, reset, returnsEffectUnsafe, revalidateUnsafe, subscribeUnsafe };
|
|
9
9
|
}
|
|
10
10
|
export declare const TypeId: typeof TypeId$1;
|
|
11
11
|
export type TypeId = typeof TypeId;
|
|
@@ -67,8 +67,8 @@ export interface FetchRequest {
|
|
|
67
67
|
}
|
|
68
68
|
export declare const CancelledError: typeof CancelledError$1;
|
|
69
69
|
export type CancelledError = CancelledError$1;
|
|
70
|
-
export declare const
|
|
71
|
-
export type
|
|
70
|
+
export declare const DisabledError: typeof DisabledError$1;
|
|
71
|
+
export type DisabledError = DisabledError$1;
|
|
72
72
|
export declare const isQuery: (value: unknown) => value is Query;
|
|
73
73
|
/**
|
|
74
74
|
* Start a request, or join the one in flight. Fails with the request's
|
|
@@ -98,6 +98,13 @@ export declare function reset<TFactory extends QueryFactory>(self: Query<TFactor
|
|
|
98
98
|
* with, before any), else the cache default's.
|
|
99
99
|
*/
|
|
100
100
|
export declare function metaUnsafe<TFactory extends QueryFactory>(self: Query<TFactory>): QueryMeta | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Whether the query's `queryFn` returns an Effect (`true`) or a promise or
|
|
103
|
+
* plain value (`false`), as of its last call, on this cache or the one its
|
|
104
|
+
* data was hydrated from. `undefined` until one has run. Bindings read typed
|
|
105
|
+
* errors as a `Result` only for Effects.
|
|
106
|
+
*/
|
|
107
|
+
export declare function returnsEffectUnsafe<TFactory extends QueryFactory>(self: Query<TFactory>): boolean | undefined;
|
|
101
108
|
/** The entry's current state. */
|
|
102
109
|
export declare function get<TFactory extends QueryFactory>(self: Query<TFactory>): Effect.Effect<State<DataOf<TFactory>>>;
|
|
103
110
|
/** {@link get}, synchronously. */
|
package/dist/query.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { CancelledError as CancelledError$1, DisabledError as DisabledError$1, TypeId as TypeId$1, changes as changes$1, entryOf, fetch as fetch$1, hasNextPageUnsafe as hasNextPageUnsafe$1, hasPreviousPageUnsafe as hasPreviousPageUnsafe$1, invalidate as invalidate$1, isQuery as isQuery$1, isStaleUnsafe as isStaleUnsafe$1, metaOf, provide, readUnsafe as readUnsafe$1, reset as reset$1, revalidate, subscribeUnsafe as subscribeUnsafe$1 } from "./entry.mjs";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
import { dual } from "effect/Function";
|
|
5
5
|
//#region src/query.ts
|
|
@@ -12,8 +12,8 @@ import { dual } from "effect/Function";
|
|
|
12
12
|
* synchronously, for renders and external stores that can't run an Effect.
|
|
13
13
|
*/
|
|
14
14
|
var query_exports = /* @__PURE__ */ __exportAll({
|
|
15
|
-
BrowserOnlyError: () => BrowserOnlyError,
|
|
16
15
|
CancelledError: () => CancelledError,
|
|
16
|
+
DisabledError: () => DisabledError,
|
|
17
17
|
TypeId: () => TypeId,
|
|
18
18
|
changes: () => changes,
|
|
19
19
|
fetch: () => fetch,
|
|
@@ -31,12 +31,13 @@ var query_exports = /* @__PURE__ */ __exportAll({
|
|
|
31
31
|
readUnsafe: () => readUnsafe,
|
|
32
32
|
refetch: () => refetch,
|
|
33
33
|
reset: () => reset,
|
|
34
|
+
returnsEffectUnsafe: () => returnsEffectUnsafe,
|
|
34
35
|
revalidateUnsafe: () => revalidateUnsafe,
|
|
35
36
|
subscribeUnsafe: () => subscribeUnsafe
|
|
36
37
|
});
|
|
37
38
|
const TypeId = TypeId$1;
|
|
38
39
|
const CancelledError = CancelledError$1;
|
|
39
|
-
const
|
|
40
|
+
const DisabledError = DisabledError$1;
|
|
40
41
|
const isQuery = isQuery$1;
|
|
41
42
|
function typed(effect) {
|
|
42
43
|
return effect;
|
|
@@ -85,6 +86,15 @@ function reset(self) {
|
|
|
85
86
|
function metaUnsafe(self) {
|
|
86
87
|
return metaOf(entryOf(self));
|
|
87
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Whether the query's `queryFn` returns an Effect (`true`) or a promise or
|
|
91
|
+
* plain value (`false`), as of its last call, on this cache or the one its
|
|
92
|
+
* data was hydrated from. `undefined` until one has run. Bindings read typed
|
|
93
|
+
* errors as a `Result` only for Effects.
|
|
94
|
+
*/
|
|
95
|
+
function returnsEffectUnsafe(self) {
|
|
96
|
+
return entryOf(self).returnsEffect;
|
|
97
|
+
}
|
|
88
98
|
/** The entry's current state. */
|
|
89
99
|
function get(self) {
|
|
90
100
|
return Effect.sync(() => getUnsafe(self));
|
|
@@ -134,4 +144,4 @@ function observerCountUnsafe(self) {
|
|
|
134
144
|
return entryOf(self).listeners.size;
|
|
135
145
|
}
|
|
136
146
|
//#endregion
|
|
137
|
-
export {
|
|
147
|
+
export { CancelledError, DisabledError, TypeId, changes, fetch, fetchNextPage, fetchPreviousPage, get, getUnsafe, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isQuery, isStaleUnsafe, metaUnsafe, observerCountUnsafe, query_exports, readUnsafe, refetch, reset, returnsEffectUnsafe, revalidateUnsafe, subscribeUnsafe };
|