@raf-query/core 0.0.16 → 0.0.17

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.17](https://github.com/KATT/raf-query/compare/0.0.16...0.0.17) (2026-10-12)
4
+
5
+ ### Features
6
+
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))
8
+
3
9
  ## [0.0.16](https://github.com/KATT/raf-query/compare/0.0.15...0.0.16) (2026-10-12)
4
10
 
5
11
  ### Bug Fixes
6
12
 
7
- * **core:** don't revalidate cached data in server verbs ([#19](https://github.com/KATT/raf-query/issues/19)) ([0ed7d9f](https://github.com/KATT/raf-query/commit/0ed7d9fefd0b70a8aa9a85c8d2c309a9fed42903))
13
+ - **core:** don't revalidate cached data in server verbs ([#19](https://github.com/KATT/raf-query/issues/19)) ([0ed7d9f](https://github.com/KATT/raf-query/commit/0ed7d9fefd0b70a8aa9a85c8d2c309a9fed42903))
8
14
 
9
15
  ## [0.0.15](https://github.com/KATT/raf-query/compare/0.0.14...0.0.15) (2026-10-12)
10
16
 
package/README.md CHANGED
@@ -556,6 +556,8 @@ Query options, accepted by `queryOptions`, `infiniteQueryOptions` and `config.de
556
556
 
557
557
  `infiniteQueryOptions` also takes `getPreviousPageParam` and `maxPages`.
558
558
 
559
+ In the browser, retries pause while `navigator.onLine` is `false`: after the retry delay, the next attempt waits for the window's `online` event. The request stays fetching meanwhile, and cancelling it (`remove`, `clear`, a restart) stops the wait. The first attempt runs regardless.
560
+
559
561
  `@raf-query/core`:
560
562
 
561
563
  | Export | Use |
@@ -0,0 +1,16 @@
1
+ import { Effect } from "effect";
2
+ //#region src/online.ts
3
+ function isOffline() {
4
+ return "window" in globalThis && "navigator" in globalThis && "onLine" in navigator && !navigator.onLine;
5
+ }
6
+ /**
7
+ * Succeeds now if the browser is online, else on the window's next `online`
8
+ * event. Interrupting it removes the listener.
9
+ */
10
+ const whenOnline = Effect.suspend(() => isOffline() ? Effect.callback((resume) => {
11
+ const onOnline = () => resume(Effect.void);
12
+ window.addEventListener("online", onOnline, { once: true });
13
+ return Effect.sync(() => window.removeEventListener("online", onOnline));
14
+ }) : Effect.void);
15
+ //#endregion
16
+ export { whenOnline };
package/dist/query.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { scheduleNotify } from "./notify.mjs";
2
+ import { whenOnline } from "./online.mjs";
2
3
  import { replaceEqualDeep } from "./share.mjs";
3
4
  import { fulfilled, pending } from "./thenable.mjs";
4
5
  import { Cause, Effect, Exit, Predicate, Schedule } from "effect";
@@ -382,7 +383,16 @@ var QueryEntry = class {
382
383
  const retry = this.#behavior("retry") ?? (this.#host.isServer ? 0 : 3);
383
384
  const countFailure = Effect.sync(() => this.#set({ failureCount: this.#state.failureCount + 1 }));
384
385
  const counted = once.pipe(Effect.tapError(() => countFailure));
385
- if (Schedule.isSchedule(retry)) return Effect.retry(counted, retry);
386
+ const online = this.#host.isServer ? Effect.void : whenOnline;
387
+ if (Schedule.isSchedule(retry)) return Effect.suspend(() => {
388
+ let first = true;
389
+ const each = Effect.suspend(() => {
390
+ const wait = first ? Effect.void : online;
391
+ first = false;
392
+ return wait.pipe(Effect.andThen(counted));
393
+ });
394
+ return Effect.retry(each, retry);
395
+ });
386
396
  const retryDelay = this.#behavior("retryDelay");
387
397
  const delayFor = (failureCount, error) => {
388
398
  if (retryDelay === void 0) return Math.min(1e3 * 2 ** (failureCount - 1), 3e4);
@@ -391,7 +401,7 @@ var QueryEntry = class {
391
401
  const attempt = counted.pipe(Effect.catch((error) => {
392
402
  const failureCount = this.#state.failureCount;
393
403
  if (!shouldRetry(retry, failureCount, error)) return Effect.fail(error);
394
- return Effect.sleep(delayFor(failureCount, error)).pipe(Effect.andThen(Effect.suspend(() => attempt)));
404
+ return Effect.sleep(delayFor(failureCount, error)).pipe(Effect.andThen(online), Effect.andThen(Effect.suspend(() => attempt)));
395
405
  }));
396
406
  return attempt;
397
407
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raf-query/core",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "Framework-agnostic core of raf-query, a render-as-you-fetch query library",
5
5
  "keywords": [
6
6
  "query",