@raf-query/core 0.10.4 → 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 CHANGED
@@ -1,11 +1,21 @@
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
+
3
13
  ## [0.10.4](https://github.com/KATT/raf-query/compare/0.10.3...0.10.4) (2026-10-16)
4
14
 
5
15
  ### Bug Fixes
6
16
 
7
- * **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)
8
- * **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))
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))
9
19
 
10
20
  ## [0.10.3](https://github.com/KATT/raf-query/compare/0.10.2...0.10.3) (2026-10-16)
11
21
 
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 { BrowserOnlyError, CacheState, CancelledError, Entry, TypeId, changes, emit, entryOf, fetch, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isBrowserOnly, isObserved, isQuery, isStaleUnsafe, make, metaOf, needsRefetch, onPlatformEvent, provide, readUnsafe, remove, reset, resume, revalidate, setData, setOptions, start, subscribeUnsafe };
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 BrowserOnlyError_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: "BrowserOnlyError";
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 `ssr: false` has no data on the server: its promise
27
- * there rejects with this, and `ensure` / `fetch` die with it.
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 BrowserOnlyError extends BrowserOnlyError_base<{
29
+ export declare class DisabledError extends DisabledError_base<{
30
30
  readonly hash: string;
31
31
  }> {
32
32
  get message(): string;
@@ -106,8 +106,8 @@ export declare function emit(cache: CacheState, event: Event): void;
106
106
  export declare function make(cache: CacheState, key: QueryKey, hash: string): Entry;
107
107
  /** Readers are subscribed; `invalidate` and focus refetch only what is read. */
108
108
  export declare function isObserved(entry: Entry): boolean;
109
- /** A server cache's entry for an `ssr: false` query: it never runs here. */
110
- export declare function isBrowserOnly(entry: Entry): boolean;
109
+ /** The entry's latest factory call returned `enabled: false`: it doesn't run. */
110
+ export declare function isDisabled(entry: Entry): boolean;
111
111
  /** Until a factory call attaches options, `meta` comes from hydration. */
112
112
  export declare function metaOf(entry: Entry): QueryMeta | undefined;
113
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 `ssr: false` has no data on the server: its promise
21
- * there rejects with this, and `ensure` / `fetch` die with it.
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 BrowserOnlyError = class extends Data.TaggedError("BrowserOnlyError") {
23
+ var DisabledError = class extends Data.TaggedError("DisabledError") {
24
24
  get message() {
25
- return `Query ${this.hash} runs in the browser only (ssr: false)`;
25
+ return `Query ${this.hash} is disabled (enabled: false)`;
26
26
  }
27
27
  };
28
28
  const Proto = {
@@ -95,7 +95,7 @@ function make(cache, key, hash) {
95
95
  },
96
96
  tasks: makeTasks(cache, scope)
97
97
  });
98
- const command = (request) => Effect.suspend(() => isBrowserOnly(entry) ? Effect.void : Effect.ignore(fetch(entry, request)));
98
+ const command = (request) => Effect.suspend(() => isDisabled(entry) ? Effect.void : Effect.ignore(fetch(entry, request)));
99
99
  const commands = {
100
100
  fetchNextPage: command({ direction: "forward" }),
101
101
  fetchPreviousPage: command({ direction: "backward" }),
@@ -115,9 +115,9 @@ function isObserved(entry) {
115
115
  function behavior(entry, name) {
116
116
  return entry.options?.[name] ?? entry.cache.defaults[name];
117
117
  }
118
- /** A server cache's entry for an `ssr: false` query: it never runs here. */
119
- function isBrowserOnly(entry) {
120
- return entry.cache.isServer && behavior(entry, "ssr") === false;
118
+ /** The entry's latest factory call returned `enabled: false`: it doesn't run. */
119
+ function isDisabled(entry) {
120
+ return behavior(entry, "enabled") === false;
121
121
  }
122
122
  /** Until a factory call attaches options, `meta` comes from hydration. */
123
123
  function metaOf(entry) {
@@ -225,7 +225,7 @@ function fetch(entry, request = {}) {
225
225
  function invalidate(entry) {
226
226
  return Effect.suspend(() => {
227
227
  set(entry, { isInvalidated: true });
228
- if (!isObserved(entry) || !entry.options || isBrowserOnly(entry)) return Effect.void;
228
+ if (!isObserved(entry) || !entry.options || isDisabled(entry)) return Effect.void;
229
229
  return Effect.ignore(begin(entry, { restart: true }));
230
230
  });
231
231
  }
@@ -244,7 +244,7 @@ function reset(entry) {
244
244
  status: "pending",
245
245
  updatedAt: 0
246
246
  });
247
- if (!entry.options || isBrowserOnly(entry) || !isObserved(entry) && !entry.inFlight) return Effect.void;
247
+ if (!entry.options || isDisabled(entry) || !isObserved(entry) && !entry.inFlight) return Effect.void;
248
248
  return Effect.ignore(begin(entry, { restart: true }));
249
249
  });
250
250
  }
@@ -291,11 +291,13 @@ function remove(entry) {
291
291
  */
292
292
  function begin(entry, request) {
293
293
  if (Predicate.isTagged(entry.scope.state, "Closed")) return Effect.fail(new CancelledError());
294
- if (isBrowserOnly(entry)) {
295
- const error = new BrowserOnlyError({ hash: entry.hash });
296
- const firstLoad = entry.pending;
297
- entry.pending = void 0;
298
- firstLoad?.reject(error);
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
+ }
299
301
  return Effect.die(error);
300
302
  }
301
303
  const options = entry.options;
@@ -332,7 +334,7 @@ function startRequest(entry, request, direction, updatedAt) {
332
334
  entry.retriesStopped = false;
333
335
  entry.signalRead = false;
334
336
  entry.tasks.cancel("gc");
335
- if (!entry.state.hasData && entry.state.status === "error") {
337
+ if (!entry.state.hasData && !entry.pending) {
336
338
  entry.pending = pending();
337
339
  set(entry, {
338
340
  error: null,
@@ -521,4 +523,4 @@ function scheduleStale(entry) {
521
523
  entry.tasks.fork("stale", Effect.sleep(Math.max(remaining, 0) + 1).pipe(Effect.andThen(Effect.sync(() => set(entry, {})))));
522
524
  }
523
525
  //#endregion
524
- export { BrowserOnlyError, CancelledError, TypeId, changes, emit, entryOf, fetch, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isBrowserOnly, isObserved, isQuery, isStaleUnsafe, make, metaOf, needsRefetch, onPlatformEvent, provide, readUnsafe, remove, reset, resume, revalidate, setData, setOptions, start, subscribeUnsafe };
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 };
@@ -1,4 +1,4 @@
1
- import { entryOf, isBrowserOnly, resume, revalidate, setData } from "./entry.mjs";
1
+ import { entryOf, isDisabled, resume, revalidate, setData } from "./entry.mjs";
2
2
  import { getUnsafe, metaUnsafe, returnsEffectUnsafe } from "./query.mjs";
3
3
  import { Data, Effect, Queue, Stream } from "effect";
4
4
  //#region src/hydration.ts
@@ -62,7 +62,7 @@ function dehydrateEntries(queries, options) {
62
62
  const filter = options.filter ?? canDehydrate;
63
63
  const sent = options.sent;
64
64
  const dehydrated = [];
65
- for (const query of queries) if (!sent?.has(query.hash) && !isBrowserOnly(entryOf(query)) && filter(query)) {
65
+ for (const query of queries) if (!sent?.has(query.hash) && !isDisabled(entryOf(query)) && filter(query)) {
66
66
  sent?.add(query.hash);
67
67
  dehydrated.push(dehydrateUnsafe(query, options));
68
68
  }
@@ -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 { BrowserOnlyError as BrowserOnlyError$1, CancelledError as CancelledError$1, TypeId as TypeId$1, entry_d_exports } from "./entry.mjs";
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 { BrowserOnlyError, CancelledError, FetchRequest, Query, State, SubscribeOptions, TypeId, changes, fetch, fetchNextPage, fetchPreviousPage, get, getUnsafe, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isQuery, isStaleUnsafe, metaUnsafe, observerCountUnsafe, readUnsafe, refetch, reset, returnsEffectUnsafe, revalidateUnsafe, subscribeUnsafe };
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 BrowserOnlyError: typeof BrowserOnlyError$1;
71
- export type BrowserOnlyError = BrowserOnlyError$1;
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
package/dist/query.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
- import { BrowserOnlyError as BrowserOnlyError$1, CancelledError as CancelledError$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";
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,
@@ -37,7 +37,7 @@ var query_exports = /* @__PURE__ */ __exportAll({
37
37
  });
38
38
  const TypeId = TypeId$1;
39
39
  const CancelledError = CancelledError$1;
40
- const BrowserOnlyError = BrowserOnlyError$1;
40
+ const DisabledError = DisabledError$1;
41
41
  const isQuery = isQuery$1;
42
42
  function typed(effect) {
43
43
  return effect;
@@ -144,4 +144,4 @@ function observerCountUnsafe(self) {
144
144
  return entryOf(self).listeners.size;
145
145
  }
146
146
  //#endregion
147
- export { BrowserOnlyError, CancelledError, TypeId, changes, fetch, fetchNextPage, fetchPreviousPage, get, getUnsafe, hasNextPageUnsafe, hasPreviousPageUnsafe, invalidate, isQuery, isStaleUnsafe, metaUnsafe, observerCountUnsafe, query_exports, readUnsafe, refetch, reset, returnsEffectUnsafe, revalidateUnsafe, subscribeUnsafe };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/core",
3
- "version": "0.10.4",
3
+ "version": "0.11.0",
4
4
  "description": "Framework-agnostic core of raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",