@gusnips/react 0.9.22 → 0.9.23

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.
@@ -1,4 +1,4 @@
1
- import type { ApiError as ApiErrorBody } from "@gusnips/http";
1
+ import type { ApiErrorBody } from "@gusnips/http";
2
2
  /**
3
3
  * A refusal, with the whole envelope intact.
4
4
  *
@@ -1 +1 @@
1
- {"version":3,"file":"api-error.d.ts","sourceRoot":"","sources":["../src/api-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,eAAe,CAAC;AAE9D;;;;;;;;;;GAUG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;gBAGzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,EAClC,IAAI,GAAE;QACJ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;KACpB;CAaT;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD"}
1
+ {"version":3,"file":"api-error.d.ts","sourceRoot":"","sources":["../src/api-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;;GAUG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5C;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;gBAGzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,EAClC,IAAI,GAAE;QACJ,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;KACpB;CAaT;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEpD"}
package/dist/query.js CHANGED
@@ -1,4 +1,4 @@
1
- import { retryDelayMs as delayFor, shouldRetry as retryRule } from "@gusnips/http/retry";
1
+ import { retryDelayMs as delayFor, isRetryable as retryRule } from "@gusnips/http/retry";
2
2
  import { ApiError } from "./api-error.js";
3
3
  /**
4
4
  * Should this failure be retried?
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gusnips/react",
3
- "version": "0.9.22",
3
+ "version": "0.9.23",
4
4
  "description": "The headless runtime under a Vite + React SPA: typed fetch client with single-flight refresh, auth store, query defaults, route guards, error boundary, stale-tab recovery, i18n bootstrap.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -80,7 +80,7 @@
80
80
  "release:major": "bun pm version major && bun publish --access public"
81
81
  },
82
82
  "dependencies": {
83
- "@gusnips/http": "0.1.6",
83
+ "@gusnips/http": "0.2.0",
84
84
  "clsx": "^2.1.1",
85
85
  "tailwind-merge": "^3.6.0"
86
86
  },
package/src/api-error.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ApiError as ApiErrorBody } from "@gusnips/http";
1
+ import type { ApiErrorBody } from "@gusnips/http";
2
2
 
3
3
  /**
4
4
  * A refusal, with the whole envelope intact.
@@ -0,0 +1,48 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { ErrorBoundary } from "./error-boundary.tsx";
3
+
4
+ /**
5
+ * The two statics are pure, which is why the reset rule lives in them: it can be checked with no
6
+ * DOM, no renderer and no thrown error.
7
+ *
8
+ * What is worth pinning is that a caught error belongs to the screen it happened on. Wrong one way,
9
+ * navigating away carries the wreckage to every page after it. Wrong the other way, the fallback
10
+ * clears itself at once and re-renders the component that just threw, which throws again: a
11
+ * flicker instead of a state. Lifted from an adopter's copy of this class, deleted when it moved
12
+ * onto the kit's.
13
+ */
14
+ const props = (resetKey: string | undefined) => ({
15
+ resetKey,
16
+ fallback: () => null,
17
+ children: null,
18
+ });
19
+
20
+ describe("ErrorBoundary", () => {
21
+ it("records the error that was thrown", () => {
22
+ const error = new TypeError("outcome is not a key of TONE");
23
+ expect(ErrorBoundary.getDerivedStateFromError(error)).toEqual({ error });
24
+ });
25
+
26
+ it("keeps the error while the route stays put", () => {
27
+ const state = { error: new Error("boom"), key: "/jobs/abc" };
28
+ expect(ErrorBoundary.getDerivedStateFromProps(props("/jobs/abc"), state)).toBeNull();
29
+ });
30
+
31
+ it("clears the error when the route changes", () => {
32
+ const state = { error: new Error("boom"), key: "/jobs/abc" };
33
+ expect(ErrorBoundary.getDerivedStateFromProps(props("/keys"), state)).toEqual({
34
+ error: null,
35
+ key: "/keys",
36
+ });
37
+ });
38
+
39
+ it("tracks the route while nothing has thrown, so the first error is scoped to it", () => {
40
+ // Without this the key would still hold the route the boundary mounted on, and the first
41
+ // error on any later route would clear itself on the next re-render.
42
+ const state = { error: null, key: "/" };
43
+ expect(ErrorBoundary.getDerivedStateFromProps(props("/usage"), state)).toEqual({
44
+ error: null,
45
+ key: "/usage",
46
+ });
47
+ });
48
+ });
package/src/query.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { retryDelayMs as delayFor, shouldRetry as retryRule } from "@gusnips/http/retry";
1
+ import { retryDelayMs as delayFor, isRetryable as retryRule } from "@gusnips/http/retry";
2
2
  import type { DefaultOptions } from "@tanstack/react-query";
3
3
  import { ApiError } from "./api-error.ts";
4
4