@raf-query/core 0.0.17 → 0.0.18

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,10 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.18](https://github.com/KATT/raf-query/compare/0.0.17...0.0.18) (2026-10-12)
4
+
5
+ ### Bug Fixes
6
+
7
+ * **core:** allow undefined query data ([#22](https://github.com/KATT/raf-query/issues/22)) ([9b85e57](https://github.com/KATT/raf-query/commit/9b85e57bf2fed4413cdbc1b49f925cc60dad695f)), references [#20](https://github.com/KATT/raf-query/issues/20)
8
+
3
9
  ## [0.0.17](https://github.com/KATT/raf-query/compare/0.0.16...0.0.17) (2026-10-12)
4
10
 
5
11
  ### Features
6
12
 
7
- * **core:** pause retries while the browser is offline ([#18](https://github.com/KATT/raf-query/issues/18)) ([a25c664](https://github.com/KATT/raf-query/commit/a25c664359fe7248cdc8d91a14d524e37b467c6c))
13
+ - **core:** pause retries while the browser is offline ([#18](https://github.com/KATT/raf-query/issues/18)) ([a25c664](https://github.com/KATT/raf-query/commit/a25c664359fe7248cdc8d91a14d524e37b467c6c))
8
14
 
9
15
  ## [0.0.16](https://github.com/KATT/raf-query/compare/0.0.15...0.0.16) (2026-10-12)
10
16
 
package/README.md CHANGED
@@ -363,6 +363,8 @@ function EditTitle(props: { post: Post }) {
363
363
  | `qc.setData(factory, input, updater)` | Write data directly |
364
364
  | `qc.getData(factory, input)` | Read cached data, or `undefined` |
365
365
 
366
+ Data can be `undefined` when the `queryFn`'s type allows it (`Promise<User | undefined>`); it's cached and reused like any other value, unlike in TanStack Query, where an `undefined` result is an error. So `getData` and an updater's `previous` return `undefined` both with no data and with `undefined` data; `qc.getQuery(factory, input).getState().hasData` tells them apart.
367
+
366
368
  ## SSR and hydration
367
369
 
368
370
  The server's query client streams its cache to the browser's query client as entries settle. Pending queries cross as promises, so the browser resumes the server's request instead of starting a new one. Components never hydrate anything themselves; a handle only needs its key to find the entry.
package/dist/client.d.mts CHANGED
@@ -34,7 +34,10 @@ export interface QueryFilter {
34
34
  }
35
35
  /** `ensure` / `fetch` arguments: the input, then load options for paged factories. */
36
36
  export type LoadArgs<TFactory extends QueryFactory> = InputArgs<TFactory> | [input: InputOf<TFactory>, options: LoadOptions<TFactory>];
37
- /** A new value, or a function of the current one. */
37
+ /**
38
+ * A new value, or a function of the current one. `previous` is `undefined`
39
+ * both with no data and with `undefined` data.
40
+ */
38
41
  export type Updater<TData> = TData | ((previous: TData | undefined) => TData);
39
42
  /** Effect-returning twins of the client's async methods. */
40
43
  export interface QueryClientEffect {
@@ -100,7 +103,10 @@ export declare class QueryClient {
100
103
  remove(filter: QueryFilter): void;
101
104
  /** Write data for a factory call. Readers re-render without suspending. */
102
105
  setData<TFactory extends QueryFactory>(factory: TFactory, input: InputOf<TFactory>, updater: Updater<DataOf<TFactory>>): void;
103
- /** Cached data for a factory call, or `undefined`. */
106
+ /**
107
+ * Cached data for a factory call, or `undefined` if there is none. Data can
108
+ * itself be `undefined`; `getQuery(...).getState().hasData` tells them apart.
109
+ */
104
110
  getData<TFactory extends QueryFactory>(factory: TFactory, ...args: InputArgs<TFactory>): DataOf<TFactory> | undefined;
105
111
  /** Every entry, for devtools and integrations. */
106
112
  getAll(): ReadonlyArray<Query>;
package/dist/client.mjs CHANGED
@@ -115,9 +115,9 @@ var QueryClient = class {
115
115
  async fetch(factory, ...args) {
116
116
  const entry = this.#build(factory, args[0]);
117
117
  await this.#load(entry, args[1]?.pages);
118
- const data = typed(entry).getState().data;
119
- if (data === void 0) throw new Error(`Query ${entry.hash} has no data`);
120
- return data;
118
+ const state = entry.getState();
119
+ if (!state.hasData) throw new Error(`Query ${entry.hash} has no data`);
120
+ return unsafeCast(state.data);
121
121
  }
122
122
  async invalidate(target, input) {
123
123
  await Promise.all(this.#match(target, input).map((entry) => entry.invalidate()));
@@ -134,7 +134,10 @@ var QueryClient = class {
134
134
  const next = isUpdateFunction(updater) ? updater(typed(entry).getState().data) : updater;
135
135
  entry.setData(next);
136
136
  }
137
- /** Cached data for a factory call, or `undefined`. */
137
+ /**
138
+ * Cached data for a factory call, or `undefined` if there is none. Data can
139
+ * itself be `undefined`; `getQuery(...).getState().hasData` tells them apart.
140
+ */
138
141
  getData(factory, ...args) {
139
142
  const options = optionsFor(factory, args[0]);
140
143
  const entry = this.#cache.get(hashKey(options.queryKey));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/core",
3
- "version": "0.0.17",
3
+ "version": "0.0.18",
4
4
  "description": "Framework-agnostic core of raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",