@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.
- package/dist/api-error.d.ts +1 -1
- package/dist/api-error.d.ts.map +1 -1
- package/dist/query.js +1 -1
- package/package.json +2 -2
- package/src/api-error.ts +1 -1
- package/src/error-boundary.test.ts +48 -0
- package/src/query.ts +1 -1
package/dist/api-error.d.ts
CHANGED
package/dist/api-error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-error.d.ts","sourceRoot":"","sources":["../src/api-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gusnips/react",
|
|
3
|
-
"version": "0.9.
|
|
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.
|
|
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
|
@@ -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,
|
|
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
|
|