@raf-query/core 0.11.1 → 0.13.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +39 -1
  2. package/README.md +28 -18
  3. package/dist/client.d.mts +163 -119
  4. package/dist/client.mjs +90 -162
  5. package/dist/entry.d.mts +73 -147
  6. package/dist/entry.mjs +314 -471
  7. package/dist/features/focus-refetch/focus-refetch.d.mts +17 -0
  8. package/dist/features/focus-refetch/focus-refetch.mjs +20 -0
  9. package/dist/features/polling/polling.d.mts +16 -0
  10. package/dist/features/polling/polling.mjs +39 -0
  11. package/dist/features/reconnect-refetch/reconnect-refetch.d.mts +17 -0
  12. package/dist/features/reconnect-refetch/reconnect-refetch.mjs +16 -0
  13. package/dist/features/shared.mjs +13 -0
  14. package/dist/guards.mjs +23 -0
  15. package/dist/hydration/hydration.d.mts +108 -0
  16. package/dist/hydration/hydration.mjs +142 -0
  17. package/dist/index.d.mts +19 -13
  18. package/dist/index.mjs +16 -13
  19. package/dist/infinite/infinite.d.mts +83 -0
  20. package/dist/infinite/infinite.mjs +120 -0
  21. package/dist/infinite/paging.d.mts +71 -0
  22. package/dist/infinite/paging.mjs +62 -0
  23. package/dist/internal.d.mts +13 -0
  24. package/dist/internal.mjs +7 -0
  25. package/dist/keys/keys.d.mts +54 -0
  26. package/dist/keys/keys.mjs +53 -0
  27. package/dist/keys/targets.d.mts +62 -0
  28. package/dist/keys/targets.mjs +85 -0
  29. package/dist/links/retry/retry.d.mts +33 -0
  30. package/dist/links/retry/retry.mjs +53 -0
  31. package/dist/links/timeout/timeout.d.mts +17 -0
  32. package/dist/links/timeout/timeout.mjs +35 -0
  33. package/dist/load.d.mts +149 -0
  34. package/dist/load.mjs +179 -0
  35. package/dist/options.d.mts +161 -332
  36. package/dist/options.mjs +28 -40
  37. package/dist/presets.d.mts +35 -0
  38. package/dist/presets.mjs +27 -0
  39. package/dist/root.d.mts +86 -0
  40. package/dist/structural-sharing/structural-sharing.mjs +32 -0
  41. package/dist/subscribe.d.mts +15 -0
  42. package/dist/subscribe.mjs +29 -0
  43. package/dist/thenable.d.mts +15 -17
  44. package/dist/thenable.mjs +25 -6
  45. package/dist/verbs.d.mts +150 -0
  46. package/dist/verbs.mjs +115 -0
  47. package/package.json +13 -9
  48. package/dist/_virtual/_rolldown/runtime.mjs +0 -13
  49. package/dist/all-keyed.d.mts +0 -18
  50. package/dist/all-keyed.mjs +0 -19
  51. package/dist/binding.d.mts +0 -92
  52. package/dist/binding.mjs +0 -186
  53. package/dist/cache.d.mts +0 -164
  54. package/dist/cache.mjs +0 -184
  55. package/dist/controls.d.mts +0 -95
  56. package/dist/controls.mjs +0 -70
  57. package/dist/hydration.d.mts +0 -84
  58. package/dist/hydration.mjs +0 -148
  59. package/dist/infinite.d.mts +0 -5
  60. package/dist/infinite.mjs +0 -103
  61. package/dist/key.d.mts +0 -18
  62. package/dist/key.mjs +0 -36
  63. package/dist/listen.mjs +0 -19
  64. package/dist/notify.mjs +0 -21
  65. package/dist/observer.d.mts +0 -110
  66. package/dist/observer.mjs +0 -300
  67. package/dist/platform.d.mts +0 -27
  68. package/dist/platform.mjs +0 -44
  69. package/dist/query.d.mts +0 -137
  70. package/dist/query.mjs +0 -147
  71. package/dist/request.mjs +0 -47
  72. package/dist/retry.mjs +0 -25
  73. package/dist/share.mjs +0 -40
@@ -0,0 +1,35 @@
1
+ import { Feature, Link } from "./client.mjs";
2
+ import { FocusRefetchMeta } from "./features/focus-refetch/focus-refetch.mjs";
3
+ import { ReconnectRefetchMeta } from "./features/reconnect-refetch/reconnect-refetch.mjs";
4
+ import { PollingMeta } from "./features/polling/polling.mjs";
5
+ import { RetryMeta } from "./links/retry/retry.mjs";
6
+ //#region src/presets.d.ts
7
+ /**
8
+ * What `recommended()` returns: its parts keep the `meta` they declare.
9
+ *
10
+ * @see https://raf-query.katt.dev/docs/important-defaults
11
+ */
12
+ export interface Recommended {
13
+ readonly features: readonly [Feature<{
14
+ readonly meta: FocusRefetchMeta;
15
+ }>, Feature<{
16
+ readonly meta: ReconnectRefetchMeta;
17
+ }>, Feature<{
18
+ readonly meta: PollingMeta;
19
+ }>];
20
+ readonly links: readonly [Link<{
21
+ readonly meta: RetryMeta;
22
+ }>];
23
+ }
24
+ /**
25
+ * The behaviors most apps want: retries, refetching on focus and reconnect,
26
+ * and polling. Spread it into the config:
27
+ *
28
+ * ```ts
29
+ * createQueryClient({ ...recommended(), staleTime: 30_000 });
30
+ * ```
31
+ *
32
+ * @see https://raf-query.katt.dev/docs/important-defaults
33
+ */
34
+ export declare function recommended(): Recommended;
35
+ //#endregion
@@ -0,0 +1,27 @@
1
+ import { focusRefetch } from "./features/focus-refetch/focus-refetch.mjs";
2
+ import { reconnectRefetch } from "./features/reconnect-refetch/reconnect-refetch.mjs";
3
+ import { polling } from "./features/polling/polling.mjs";
4
+ import { retry } from "./links/retry/retry.mjs";
5
+ //#region src/presets.ts
6
+ /**
7
+ * The behaviors most apps want: retries, refetching on focus and reconnect,
8
+ * and polling. Spread it into the config:
9
+ *
10
+ * ```ts
11
+ * createQueryClient({ ...recommended(), staleTime: 30_000 });
12
+ * ```
13
+ *
14
+ * @see https://raf-query.katt.dev/docs/important-defaults
15
+ */
16
+ function recommended() {
17
+ return {
18
+ features: [
19
+ focusRefetch(),
20
+ reconnectRefetch(),
21
+ polling()
22
+ ],
23
+ links: [retry()]
24
+ };
25
+ }
26
+ //#endregion
27
+ export { recommended };
@@ -0,0 +1,86 @@
1
+ //#region src/root.d.ts
2
+ /**
3
+ * Root types, the way tRPC v12 types a client from its links: each link and
4
+ * feature declares the `meta` fields it reads, a client's `meta` is what its
5
+ * parts declare, and builders bound to a root (`bindQueryOptions`) carry it
6
+ * as a phantom on the options they build.
7
+ */
8
+ /**
9
+ * A query's `meta` when its builder isn't bound to a root.
10
+ *
11
+ * @see https://raf-query.katt.dev/docs/links-and-features
12
+ */
13
+ export type QueryMeta = Readonly<Record<string, unknown>>;
14
+ /** What a link or feature declares: the `meta` fields it reads. */
15
+ export interface Decl {
16
+ readonly meta?: object;
17
+ }
18
+ /** A root's types. */
19
+ export interface RootTypes {
20
+ readonly meta: object;
21
+ }
22
+ /** The root of the unbound builders. A type only, never a value. */
23
+ export interface DefaultTypes {
24
+ readonly "~default": true;
25
+ readonly meta: QueryMeta;
26
+ }
27
+ /**
28
+ * The root of a client typed only as `QueryClient`: any root. The one way
29
+ * an invariant phantom takes every root.
30
+ */
31
+ export type AnyRoot = any;
32
+ /** Whether `TTypes` is {@link AnyRoot}. */
33
+ export type IsAnyRoot<TTypes> = 0 extends 1 & TTypes ? true : false;
34
+ /**
35
+ * Phantom carrier of a part's declaration, `undefined` at runtime.
36
+ * Invariant, so a part that declares nothing doesn't absorb the
37
+ * declarations of the others in an array.
38
+ */
39
+ export interface Declares<TDecl extends Decl> {
40
+ readonly "~decl"?: {
41
+ readonly in: (decl: TDecl) => void;
42
+ readonly out: TDecl;
43
+ };
44
+ }
45
+ /** Any link or feature, whatever it declares. */
46
+ export interface AnyPart {
47
+ readonly "~decl"?: {
48
+ readonly in: (decl: never) => void;
49
+ readonly out: unknown;
50
+ };
51
+ }
52
+ /**
53
+ * The `meta` a declaration adds to its root. Every declared key is present
54
+ * and may be `undefined`: roots of all-optional metas would be assignable to
55
+ * one another. Queries pass a `Partial` of it.
56
+ */
57
+ export type MetaOfDecl<TDecl> = TDecl extends {
58
+ readonly meta?: infer TMeta extends object;
59
+ } ? Present<TMeta> : unknown;
60
+ /**
61
+ * Every key of `T` required, its value possibly `undefined`. Mapping over
62
+ * `Exclude<keyof T, never>` rather than `keyof T` drops the modifiers
63
+ * without dropping `undefined`, which `-?` would.
64
+ */
65
+ type Present<T> = { readonly [K in Exclude<keyof T, never>]: T[K] | undefined; };
66
+ type DeclOf<TPart> = TPart extends {
67
+ readonly "~decl"?: {
68
+ readonly out: infer TDecl;
69
+ };
70
+ } ? TDecl : never;
71
+ type Intersect<TUnion> = (TUnion extends unknown ? (value: TUnion) => void : never) extends ((value: infer TIntersection) => void) ? TIntersection : never;
72
+ type Flat<T> = { readonly [K in keyof T]: T[K]; };
73
+ /** A root's `meta`: what its links and features declare. */
74
+ export type MetaOf<TParts extends ReadonlyArray<AnyPart>> = [DeclOf<TParts[number]>] extends [never] ? Flat<unknown> : Flat<Intersect<MetaOfDecl<DeclOf<TParts[number]>>>>;
75
+ declare const rootBrand: unique symbol;
76
+ /** Phantom carrier of the root a factory's builder is bound to. Never set at runtime. */
77
+ export interface RootTag<TTypes extends RootTypes> {
78
+ readonly [rootBrand]: TTypes;
79
+ }
80
+ /** A root's types, from a client or from a function that makes one. */
81
+ export type RootOf<T> = T extends ((...args: never) => infer TClient) ? RootOf<TClient> : T extends {
82
+ readonly "~types"?: {
83
+ readonly root: (types: infer TTypes extends RootTypes) => unknown;
84
+ };
85
+ } ? TTypes : never;
86
+ //#endregion
@@ -0,0 +1,32 @@
1
+ //#region src/structural-sharing/structural-sharing.ts
2
+ function isPlainArray(value) {
3
+ return Array.isArray(value) && value.length === Object.keys(value).length;
4
+ }
5
+ function isPlainObject(value) {
6
+ if (typeof value !== "object" || value === null) return false;
7
+ const prototype = Object.getPrototypeOf(value);
8
+ return prototype === Object.prototype || prototype === null;
9
+ }
10
+ /**
11
+ * `next`, reusing every part of `previous` that is deeply equal to it, so
12
+ * unchanged objects keep their identity and memoized readers skip work.
13
+ */
14
+ function replaceEqualDeep(previous, next) {
15
+ if (Object.is(previous, next)) return previous;
16
+ const arrays = isPlainArray(previous) && isPlainArray(next);
17
+ if (!arrays && !(isPlainObject(previous) && isPlainObject(next))) return next;
18
+ const before = previous;
19
+ const after = next;
20
+ const names = Object.keys(after);
21
+ let same = names.length === Object.keys(before).length;
22
+ const values = names.map((name) => {
23
+ const own = Object.hasOwn(before, name);
24
+ const value = replaceEqualDeep(own ? before[name] : void 0, after[name]);
25
+ if (!own || value !== before[name]) same = false;
26
+ return value;
27
+ });
28
+ if (same) return previous;
29
+ return arrays ? values : Object.fromEntries(names.map((name, index) => [name, values[index]]));
30
+ }
31
+ //#endregion
32
+ export { replaceEqualDeep };
@@ -0,0 +1,15 @@
1
+ //#region src/subscribe.d.ts
2
+ /**
3
+ * The kernel's one subscription primitive: `subscribe(listener, { signal })`.
4
+ * Unsubscribe by aborting the signal, or by calling what it returns. There
5
+ * is no error channel: errors live in entry state.
6
+ */
7
+ export interface SubscribeOptions {
8
+ readonly signal?: AbortSignal;
9
+ }
10
+ export interface Listeners<TEvent> {
11
+ emit(event: TEvent): void;
12
+ readonly size: number;
13
+ subscribe(listener: (event: TEvent) => void, options?: SubscribeOptions): () => void;
14
+ }
15
+ //#endregion
@@ -0,0 +1,29 @@
1
+ //#region src/subscribe.ts
2
+ function listeners(onSizeChange) {
3
+ const set = /* @__PURE__ */ new Set();
4
+ return {
5
+ emit(event) {
6
+ for (const item of set) item.listener(event);
7
+ },
8
+ get size() {
9
+ return set.size;
10
+ },
11
+ subscribe(listener, options) {
12
+ const signal = options?.signal;
13
+ if (signal?.aborted) return () => {};
14
+ const item = { listener };
15
+ set.add(item);
16
+ onSizeChange?.(set.size);
17
+ const unsubscribe = () => {
18
+ if (set.delete(item)) {
19
+ signal?.removeEventListener("abort", unsubscribe);
20
+ onSizeChange?.(set.size);
21
+ }
22
+ };
23
+ signal?.addEventListener("abort", unsubscribe, { once: true });
24
+ return unsubscribe;
25
+ }
26
+ };
27
+ }
28
+ //#endregion
29
+ export { listeners };
@@ -1,31 +1,29 @@
1
1
  //#region src/thenable.d.ts
2
2
  /**
3
- * Promises that carry their own result, in the fields React's `use()` reads
4
- * before suspending (`status`, `value`, `reason`). A settled one can be read
3
+ * Promises that carry their own result in the fields React's `use()` reads
4
+ * before suspending (`status`, `value`, `reason`). A settled one is read
5
5
  * synchronously, so React renders it without a fallback.
6
+ *
7
+ * @see https://raf-query.katt.dev/docs/reading-queries
6
8
  */
7
- interface PendingStatus {
8
- readonly status: "pending";
9
- }
10
- interface FulfilledStatus<T> {
11
- readonly status: "fulfilled";
12
- readonly value: T;
13
- }
14
- interface RejectedStatus {
9
+ export type Thenable<T> = Promise<T> & ({
15
10
  readonly reason: unknown;
16
11
  readonly status: "rejected";
17
- }
18
- /**
19
- * A promise that says whether it has settled, and with what. `status` moves
20
- * from `"pending"` to `"fulfilled"` (with `value`) or `"rejected"` (with
21
- * `reason`) once, when the promise settles.
22
- */
23
- export type Thenable<T> = Promise<T> & (FulfilledStatus<T> | PendingStatus | RejectedStatus);
12
+ } | {
13
+ readonly status: "fulfilled";
14
+ readonly value: T;
15
+ } | {
16
+ readonly status: "pending";
17
+ });
24
18
  export declare function fulfilled<T>(value: T): Thenable<T>;
19
+ export declare function rejected<T>(reason: unknown): Thenable<T>;
25
20
  export interface Pending<T> {
26
21
  readonly promise: Thenable<T>;
27
22
  reject(reason: unknown): void;
28
23
  resolve(value: T): void;
29
24
  }
25
+ /** A pending thenable that settles in place, so `use()` resumes on it. */
30
26
  export declare function pending<T>(): Pending<T>;
27
+ /** `thenable` with `map` applied to its value, cached per source thenable. */
28
+ export declare function mapThenable<T, U>(cache: WeakMap<Thenable<unknown>, Thenable<unknown>>, thenable: Thenable<T>, map: (value: T) => U): Thenable<U>;
31
29
  //#endregion
package/dist/thenable.mjs CHANGED
@@ -1,9 +1,4 @@
1
1
  //#region src/thenable.ts
2
- /**
3
- * Promises that carry their own result, in the fields React's `use()` reads
4
- * before suspending (`status`, `value`, `reason`). A settled one can be read
5
- * synchronously, so React renders it without a fallback.
6
- */
7
2
  const noop = () => {};
8
3
  function fulfilled(value) {
9
4
  return Object.assign(Promise.resolve(value), {
@@ -11,6 +6,15 @@ function fulfilled(value) {
11
6
  value
12
7
  });
13
8
  }
9
+ function rejected(reason) {
10
+ const promise = Promise.reject(reason);
11
+ promise.catch(noop);
12
+ return Object.assign(promise, {
13
+ reason,
14
+ status: "rejected"
15
+ });
16
+ }
17
+ /** A pending thenable that settles in place, so `use()` resumes on it. */
14
18
  function pending() {
15
19
  const deferred = Promise.withResolvers();
16
20
  const promise = Object.assign(deferred.promise, { status: "pending" });
@@ -33,5 +37,20 @@ function pending() {
33
37
  }
34
38
  };
35
39
  }
40
+ /** `thenable` with `map` applied to its value, cached per source thenable. */
41
+ function mapThenable(cache, thenable, map) {
42
+ const cached = cache.get(thenable);
43
+ if (cached) return cached;
44
+ let mapped;
45
+ if (thenable.status === "fulfilled") mapped = fulfilled(map(thenable.value));
46
+ else if (thenable.status === "rejected") mapped = rejected(thenable.reason);
47
+ else {
48
+ const next = pending();
49
+ thenable.then((value) => next.resolve(map(value)), (error) => next.reject(error));
50
+ mapped = next.promise;
51
+ }
52
+ cache.set(thenable, mapped);
53
+ return mapped;
54
+ }
36
55
  //#endregion
37
- export { fulfilled, pending };
56
+ export { fulfilled, mapThenable, pending, rejected };
@@ -0,0 +1,150 @@
1
+ import { Group } from "./keys/keys.mjs";
2
+ import { IsAnyRoot, RootTypes } from "./root.mjs";
3
+ import { AnyInvalidation, AnyTarget, ParamArgs, Target } from "./keys/targets.mjs";
4
+ import { InputArgs, InputOf, QueryFactory, QueryFnDataOf, RootOfFactory } from "./options.mjs";
5
+ import { QueryClient } from "./client.mjs";
6
+ //#region src/verbs.d.ts
7
+ type DeepPartial<T> = T extends object ? { readonly [TName in keyof T]?: DeepPartial<T[TName]>; } : T;
8
+ /**
9
+ * What `invalidateMany(factory, partial)` takes: part of the factory's
10
+ * input, whatever its key looks like.
11
+ *
12
+ * @see https://raf-query.katt.dev/docs/query-invalidation
13
+ */
14
+ export type PartialInput<TFactory extends QueryFactory> = DeepPartial<InputOf<TFactory>>;
15
+ /**
16
+ * The clients a factory's verbs take: its root's, or any client for a
17
+ * factory from an unbound builder.
18
+ *
19
+ * @see https://raf-query.katt.dev/docs/links-and-features#typing-meta-by-its-root
20
+ */
21
+ export type ClientFor<TFactory extends QueryFactory> = QueryClient<RootOfFactory<TFactory>>;
22
+ /**
23
+ * A target a client's root can match: its `where` reads that root's `meta`.
24
+ * A client typed only as `QueryClient` (from `useQueryClient()`, say) may
25
+ * be of any root, so it takes any target.
26
+ */
27
+ export type TargetFor<TTypes extends RootTypes, TParam> = IsAnyRoot<TTypes> extends true ? Target<never, TParam> : Target<NoInfer<TTypes["meta"]>, TParam>;
28
+ type ParamOf<TTarget> = TTarget extends {
29
+ readonly where: (query: never, param: infer TParam) => boolean;
30
+ } ? TParam : never;
31
+ /** A factory, if the client's root is its root; else nothing fits. */
32
+ type FactoryFor<TTypes extends RootTypes, TFactory extends QueryFactory> = [QueryClient<TTypes>] extends [ClientFor<TFactory>] ? TFactory : never;
33
+ /** A target on its own, if it needs no parameter; else with its parameter. */
34
+ type BareTarget<TTypes extends RootTypes, TParam> = [] extends ParamArgs<TParam> ? TargetFor<TTypes, TParam> : readonly [TargetFor<TTypes, TParam>, TParam];
35
+ type AnyItem = AnyTarget | Group | QueryFactory | readonly [AnyTarget | QueryFactory, unknown];
36
+ /**
37
+ * What one element of a target list must be, given what was passed: a
38
+ * group, a factory of the client's root, a factory with a partial input, a
39
+ * target, or a target with its parameter.
40
+ */
41
+ type Item<TTypes extends RootTypes, TItem> = TItem extends Group ? Group : TItem extends QueryFactory ? FactoryFor<TTypes, TItem> : TItem extends AnyTarget ? BareTarget<TTypes, ParamOf<TItem>> : TItem extends readonly [infer TFirst, unknown] ? TFirst extends QueryFactory ? readonly [FactoryFor<TTypes, TFirst>, PartialInput<TFirst>] : TFirst extends AnyTarget ? readonly [TargetFor<TTypes, ParamOf<TFirst>>, ParamOf<TFirst>] : AnyItem : AnyItem;
42
+ /**
43
+ * Several targets for one verb call, each checked on its own: a group, a
44
+ * factory, `[factory, partial]`, a target, or `[target, param]`.
45
+ */
46
+ export type TargetList<TTypes extends RootTypes, TItems extends ReadonlyArray<unknown>> = { readonly [TIndex in keyof TItems]: Item<TTypes, TItems[TIndex]>; };
47
+ /** The data `setData` writes: plain for a query, paged for an infinite one. */
48
+ type WritableData<TFactory extends QueryFactory> = QueryFnDataOf<TFactory>;
49
+ /**
50
+ * Mark one query stale: a factory and its full input. If it's read, it
51
+ * refetches; resolves when that settles.
52
+ *
53
+ * @see https://raf-query.katt.dev/docs/query-invalidation
54
+ */
55
+ export declare function invalidateOne<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): Promise<void>;
56
+ /**
57
+ * Mark queries stale: a factory's (optionally only those whose input
58
+ * matches `partial`), a group's (keys that start with its path, whether
59
+ * the group built them or not), or those a target's `where` picks. Read
60
+ * queries refetch now; the rest when next read. Resolves when the
61
+ * refetches settle.
62
+ *
63
+ * Pass a list to invalidate several targets in one call: each query they
64
+ * cover refetches once, and the refetches run side by side. Awaiting one
65
+ * call after another runs them one after another instead.
66
+ *
67
+ * ```ts
68
+ * await invalidateMany(client, [authors, [commentsQuery, { slug }], [ownedBy, "editorial"]]);
69
+ * ```
70
+ *
71
+ * @see https://raf-query.katt.dev/docs/query-invalidation#several-targets
72
+ */
73
+ export declare function invalidateMany<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, partial?: PartialInput<TFactory>): Promise<void>;
74
+ export declare function invalidateMany(client: QueryClient, group: Group): Promise<void>;
75
+ export declare function invalidateMany<TTypes extends RootTypes, TParam = never>(client: QueryClient<TTypes>, target: TargetFor<TTypes, TParam>, ...param: ParamArgs<NoInfer<TParam>>): Promise<void>;
76
+ export declare function invalidateMany<TTypes extends RootTypes, const TItems extends ReadonlyArray<unknown>>(client: QueryClient<TTypes>, targets: TargetList<TTypes, TItems>): Promise<void>;
77
+ /**
78
+ * Mark every query stale; read ones refetch. For sign-out, or after any write.
79
+ *
80
+ * @see https://raf-query.katt.dev/docs/query-invalidation
81
+ */
82
+ export declare function invalidateAll(client: QueryClient): Promise<void>;
83
+ /**
84
+ * Drop one query's data and error. If it's read, it suspends and refetches;
85
+ * resolves when that settles.
86
+ *
87
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
88
+ */
89
+ export declare function resetOne<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): Promise<void>;
90
+ /**
91
+ * {@link resetOne} for every query a target, or a list of them, covers.
92
+ *
93
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
94
+ */
95
+ export declare function resetMany<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, partial?: PartialInput<TFactory>): Promise<void>;
96
+ export declare function resetMany(client: QueryClient, group: Group): Promise<void>;
97
+ export declare function resetMany<TTypes extends RootTypes, TParam = never>(client: QueryClient<TTypes>, target: TargetFor<TTypes, TParam>, ...param: ParamArgs<NoInfer<TParam>>): Promise<void>;
98
+ export declare function resetMany<TTypes extends RootTypes, const TItems extends ReadonlyArray<unknown>>(client: QueryClient<TTypes>, targets: TargetList<TTypes, TItems>): Promise<void>;
99
+ /**
100
+ * {@link resetOne} for every query.
101
+ *
102
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
103
+ */
104
+ export declare function resetAll(client: QueryClient): Promise<void>;
105
+ /**
106
+ * Remove one query from the cache, aborting its request.
107
+ *
108
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
109
+ */
110
+ export declare function removeOne<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): void;
111
+ /**
112
+ * {@link removeOne} for every query a target, or a list of them, covers.
113
+ *
114
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
115
+ */
116
+ export declare function removeMany<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, partial?: PartialInput<TFactory>): void;
117
+ export declare function removeMany(client: QueryClient, group: Group): void;
118
+ export declare function removeMany<TTypes extends RootTypes, TParam = never>(client: QueryClient<TTypes>, target: TargetFor<TTypes, TParam>, ...param: ParamArgs<NoInfer<TParam>>): void;
119
+ export declare function removeMany<TTypes extends RootTypes, const TItems extends ReadonlyArray<unknown>>(client: QueryClient<TTypes>, targets: TargetList<TTypes, TItems>): void;
120
+ /**
121
+ * Remove every query, aborting their requests.
122
+ *
123
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
124
+ */
125
+ export declare function removeAll(client: QueryClient): void;
126
+ /** New data for `setData`, or a function from the current data to it. */
127
+ type Updater<TFactory extends QueryFactory> = ((previous: WritableData<TFactory> | undefined) => WritableData<TFactory>) | WritableData<TFactory>;
128
+ /**
129
+ * Write a query's data, as if a request had just returned it. `updater`
130
+ * gets the current data, or `undefined` if there is none. A factory that
131
+ * takes no input (or an optional one) skips the input:
132
+ * `setData(client, feedQuery, updater)`.
133
+ *
134
+ * @see https://raf-query.katt.dev/docs/mutations#updates-from-mutation-responses
135
+ */
136
+ export declare function setData<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...updater: [] extends Parameters<TFactory> ? [updater: Updater<TFactory>] : never): void;
137
+ export declare function setData<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, input: Parameters<TFactory> extends [] ? never : Parameters<TFactory>[0], updater: Updater<TFactory>): void;
138
+ /**
139
+ * A query's cached data (before `select`), or `undefined`.
140
+ *
141
+ * @see https://raf-query.katt.dev/docs/api-reference#changing-the-cache
142
+ */
143
+ export declare function getData<TFactory extends QueryFactory>(client: ClientFor<TFactory>, factory: TFactory, ...input: InputArgs<TFactory>): WritableData<TFactory> | undefined;
144
+ /**
145
+ * How many queries have a request in flight, optionally only a factory's, a group's or a target's.
146
+ *
147
+ * @see https://raf-query.katt.dev/docs/background-fetching-indicators
148
+ */
149
+ export declare function isFetching(client: QueryClient, target?: AnyInvalidation): number;
150
+ //#endregion
package/dist/verbs.mjs ADDED
@@ -0,0 +1,115 @@
1
+ import { isArray, isFunction } from "./guards.mjs";
2
+ import { hashKey } from "./keys/keys.mjs";
3
+ import { entryStamp, matches, stampFor } from "./keys/targets.mjs";
4
+ import { optionsOf } from "./options.mjs";
5
+ import { entryOf, invalidate, remove, reset, write } from "./entry.mjs";
6
+ //#region src/verbs.ts
7
+ function hashOf(factory, input) {
8
+ return hashKey(optionsOf(factory, input).queryKey);
9
+ }
10
+ /** A stamp per target: one target and its argument, or each of a list. */
11
+ function stampsOf(targets, arg, at) {
12
+ return (isArray(targets) ? targets : [[targets, arg]]).map((item) => isArray(item) ? stampFor(item[0], item[1], at) : stampFor(item, void 0, at));
13
+ }
14
+ function entriesMatching(client, stamps) {
15
+ return [...client["~entries"].values()].filter((entry) => stamps.some((stamp) => matches(entry, stamp)));
16
+ }
17
+ function settle(outcomes) {
18
+ return Promise.all(outcomes).then(() => {});
19
+ }
20
+ /**
21
+ * Mark one query stale: a factory and its full input. If it's read, it
22
+ * refetches; resolves when that settles.
23
+ *
24
+ * @see https://raf-query.katt.dev/docs/query-invalidation
25
+ */
26
+ function invalidateOne(client, factory, ...input) {
27
+ return invalidate(client, (at) => [entryStamp(hashOf(factory, input[0]), at)]);
28
+ }
29
+ function invalidateMany(client, target, partial) {
30
+ return invalidate(client, (at) => stampsOf(target, partial, at));
31
+ }
32
+ /**
33
+ * Mark every query stale; read ones refetch. For sign-out, or after any write.
34
+ *
35
+ * @see https://raf-query.katt.dev/docs/query-invalidation
36
+ */
37
+ function invalidateAll(client) {
38
+ return invalidate(client, (at) => [{
39
+ at,
40
+ kind: "all"
41
+ }]);
42
+ }
43
+ function oneEntry(client, factory, input) {
44
+ return client["~entries"].get(hashOf(factory, input));
45
+ }
46
+ /**
47
+ * Drop one query's data and error. If it's read, it suspends and refetches;
48
+ * resolves when that settles.
49
+ *
50
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
51
+ */
52
+ function resetOne(client, factory, ...input) {
53
+ const entry = oneEntry(client, factory, input[0]);
54
+ return settle(entry ? [reset(entry)] : []);
55
+ }
56
+ function resetMany(client, target, partial) {
57
+ return settle(entriesMatching(client, stampsOf(target, partial, 0)).map(reset));
58
+ }
59
+ /**
60
+ * {@link resetOne} for every query.
61
+ *
62
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
63
+ */
64
+ function resetAll(client) {
65
+ return settle([...client["~entries"].values()].map(reset));
66
+ }
67
+ /**
68
+ * Remove one query from the cache, aborting its request.
69
+ *
70
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
71
+ */
72
+ function removeOne(client, factory, ...input) {
73
+ const entry = oneEntry(client, factory, input[0]);
74
+ if (entry) remove(entry);
75
+ }
76
+ function removeMany(client, target, partial) {
77
+ for (const entry of entriesMatching(client, stampsOf(target, partial, 0))) remove(entry);
78
+ }
79
+ /**
80
+ * Remove every query, aborting their requests.
81
+ *
82
+ * @see https://raf-query.katt.dev/docs/query-invalidation#invalidate-reset-or-remove
83
+ */
84
+ function removeAll(client) {
85
+ for (const entry of client["~entries"].values()) remove(entry);
86
+ }
87
+ function setData(client, factory, ...args) {
88
+ const [input, updater] = args.length < 2 ? [void 0, args[0]] : args;
89
+ const entry = entryOf(client, factory, input);
90
+ const previous = entry.state.hasData ? entry.state.data : void 0;
91
+ const data = isFunction(updater) ? updater(previous) : updater;
92
+ write(entry, data, client.clock.now(), ++client["~seq"]);
93
+ }
94
+ /**
95
+ * A query's cached data (before `select`), or `undefined`.
96
+ *
97
+ * @see https://raf-query.katt.dev/docs/api-reference#changing-the-cache
98
+ */
99
+ function getData(client, factory, ...input) {
100
+ const entry = oneEntry(client, factory, input[0]);
101
+ return entry?.state.hasData ? entry.state.data : void 0;
102
+ }
103
+ /**
104
+ * How many queries have a request in flight, optionally only a factory's, a group's or a target's.
105
+ *
106
+ * @see https://raf-query.katt.dev/docs/background-fetching-indicators
107
+ */
108
+ function isFetching(client, target) {
109
+ return entriesMatching(client, [target === void 0 ? {
110
+ at: 0,
111
+ kind: "all"
112
+ } : stampFor(target, void 0, 0)]).filter((entry) => entry.state.isFetching).length;
113
+ }
114
+ //#endregion
115
+ export { getData, invalidateAll, invalidateMany, invalidateOne, isFetching, removeAll, removeMany, removeOne, resetAll, resetMany, resetOne, setData };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/core",
3
- "version": "0.11.1",
3
+ "version": "0.13.0",
4
4
  "description": "Framework-agnostic core of raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",
@@ -31,18 +31,22 @@
31
31
  "type": "module",
32
32
  "sideEffects": false,
33
33
  "exports": {
34
- ".": "./dist/index.mjs"
35
- },
36
- "peerDependencies": {
37
- "effect": "^4.0.0"
34
+ ".": "./dist/index.mjs",
35
+ "./internal": "./dist/internal.mjs"
38
36
  },
39
37
  "devDependencies": {
40
- "@effect/vitest": "4.0.1",
38
+ "@testing-library/react": "16.3.3",
41
39
  "@types/node": "26.6.4",
40
+ "@types/react": "19.3.0",
41
+ "@types/react-dom": "19.3.0",
42
42
  "@vitest/coverage-v8": "5.0.1",
43
- "effect": "^4.0.1",
43
+ "fast-check": "4.10.2",
44
+ "happy-dom": "21.0.1",
45
+ "react": "19.3.0",
46
+ "react-dom": "19.3.0",
44
47
  "typescript": "7.0.2",
45
- "vite-plus": "1.0.0"
48
+ "vite-plus": "1.0.0",
49
+ "vitest": "5.0.1"
46
50
  },
47
51
  "publishConfig": {
48
52
  "access": "public",
@@ -54,7 +58,7 @@
54
58
  "scripts": {
55
59
  "build": "vp pack",
56
60
  "test": "vp test",
57
- "typecheck": "tsc",
61
+ "typecheck": "tsc && tsc -p tsconfig.no-node.json",
58
62
  "publish:npm": "pnpm pack --out package.tgz && npm publish package.tgz --access public && rm package.tgz"
59
63
  }
60
64
  }
@@ -1,13 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- //#endregion
13
- export { __exportAll };
@@ -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