@gusnips/react 0.9.17 → 0.9.19
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/query.d.ts +2 -2
- package/dist/query.js +2 -2
- package/dist/supabase-session.d.ts +7 -2
- package/dist/supabase-session.d.ts.map +1 -1
- package/dist/supabase-session.js +7 -2
- package/dist/supabase-session.js.map +1 -1
- package/package.json +2 -2
- package/src/query.test.ts +13 -4
- package/src/query.ts +2 -2
- package/src/supabase-session.test.ts +3 -2
- package/src/supabase-session.ts +7 -2
package/dist/query.d.ts
CHANGED
|
@@ -66,8 +66,8 @@ export interface QueryDefaultsOptions {
|
|
|
66
66
|
*/
|
|
67
67
|
export declare function shouldRetry(error: unknown, durableLimitCodes?: readonly string[], maxRetryWaitSecs?: number): boolean;
|
|
68
68
|
/**
|
|
69
|
-
* How long before the next attempt: the server's stated wait when there is one,
|
|
70
|
-
*
|
|
69
|
+
* How long before the next attempt: the server's stated wait when there is one, an exponential
|
|
70
|
+
* backoff with jitter otherwise, and never less than the backoff — a `Retry-After: 0` is a
|
|
71
71
|
* server saying "immediately", which for a client that just got refused is still too soon.
|
|
72
72
|
*/
|
|
73
73
|
export declare function retryDelayMs(attemptIndex: number, error: unknown): number;
|
package/dist/query.js
CHANGED
|
@@ -15,8 +15,8 @@ export function shouldRetry(error, durableLimitCodes = [], maxRetryWaitSecs) {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* How long before the next attempt: the server's stated wait when there is one,
|
|
19
|
-
*
|
|
18
|
+
* How long before the next attempt: the server's stated wait when there is one, an exponential
|
|
19
|
+
* backoff with jitter otherwise, and never less than the backoff — a `Retry-After: 0` is a
|
|
20
20
|
* server saying "immediately", which for a client that just got refused is still too soon.
|
|
21
21
|
*/
|
|
22
22
|
export function retryDelayMs(attemptIndex, error) {
|
|
@@ -33,8 +33,13 @@ export interface SupabaseSessionAuth {
|
|
|
33
33
|
* whichever version happens to be installed, which is not the same as being right, and a fleet
|
|
34
34
|
* installs several versions at once. It is also a LIST rather than a range, so it has holes at
|
|
35
35
|
* every version, drift or no drift: at 2.112 nothing covers 505 through 519 or 531 up, and a
|
|
36
|
-
* 507 or a 599
|
|
37
|
-
*
|
|
36
|
+
* 507 or a 599 with a JSON body arrives as a plain `AuthApiError`. Pinning a recent SDK does not
|
|
37
|
+
* make the status clause redundant.
|
|
38
|
+
*
|
|
39
|
+
* The same statuses with a body that is NOT JSON — a proxy's HTML page — arrive as an
|
|
40
|
+
* `AuthUnknownError`, which carries no status at any status, so nothing here can tell that 507
|
|
41
|
+
* from a malformed 400. It answers false for both, on purpose: reading an unreadable 4xx as an
|
|
42
|
+
* outage would leave a dead session retrying forever, which is the other half of the same bug.
|
|
38
43
|
*
|
|
39
44
|
* Read the version a tree really serves with `bun why @supabase/auth-js`, which prints one
|
|
40
45
|
* heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase-session.d.ts","sourceRoot":"","sources":["../src/supabase-session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,UAAU,qBAAqB;IAC7B,IAAI,EAAE;QAAE,OAAO,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,CAAC;CACpD;AAED,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC,UAAU,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC7C,cAAc,IAAI,OAAO,CAAC,qBAAqB,GAAG;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtE,OAAO,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxC;AAOD
|
|
1
|
+
{"version":3,"file":"supabase-session.d.ts","sourceRoot":"","sources":["../src/supabase-session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,UAAU,qBAAqB;IAC7B,IAAI,EAAE;QAAE,OAAO,EAAE;YAAE,YAAY,EAAE,MAAM,CAAA;SAAE,GAAG,IAAI,CAAA;KAAE,CAAC;CACpD;AAED,8FAA8F;AAC9F,MAAM,WAAW,mBAAmB;IAClC,UAAU,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC7C,cAAc,IAAI,OAAO,CAAC,qBAAqB,GAAG;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtE,OAAO,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxC;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASpD;AAaD;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,cAAc,CAsBtF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,aAAa,GACvB,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,OAAO,CAAC;AAiB5E,qFAAqF;AACrF,MAAM,MAAM,YAAY;AACtB,0FAA0F;AACxF;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,aAAa,CAAA;CAAE;AAChE;;;;;;GAMG;GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AACH;;;;;GAKG;GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE;AAClF,qFAAqF;GACnF;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,IAAI,SAAK,GAAG,YAAY,CA6B3F"}
|
package/dist/supabase-session.js
CHANGED
|
@@ -16,8 +16,13 @@ import { isAuthError, isAuthRetryableFetchError } from "@supabase/supabase-js";
|
|
|
16
16
|
* whichever version happens to be installed, which is not the same as being right, and a fleet
|
|
17
17
|
* installs several versions at once. It is also a LIST rather than a range, so it has holes at
|
|
18
18
|
* every version, drift or no drift: at 2.112 nothing covers 505 through 519 or 531 up, and a
|
|
19
|
-
* 507 or a 599
|
|
20
|
-
*
|
|
19
|
+
* 507 or a 599 with a JSON body arrives as a plain `AuthApiError`. Pinning a recent SDK does not
|
|
20
|
+
* make the status clause redundant.
|
|
21
|
+
*
|
|
22
|
+
* The same statuses with a body that is NOT JSON — a proxy's HTML page — arrive as an
|
|
23
|
+
* `AuthUnknownError`, which carries no status at any status, so nothing here can tell that 507
|
|
24
|
+
* from a malformed 400. It answers false for both, on purpose: reading an unreadable 4xx as an
|
|
25
|
+
* outage would leave a dead session retrying forever, which is the other half of the same bug.
|
|
21
26
|
*
|
|
22
27
|
* Read the version a tree really serves with `bun why @supabase/auth-js`, which prints one
|
|
23
28
|
* heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase-session.js","sourceRoot":"","sources":["../src/supabase-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,yBAAyB,EAAuB,MAAM,uBAAuB,CAAC;AAmBpG
|
|
1
|
+
{"version":3,"file":"supabase-session.js","sourceRoot":"","sources":["../src/supabase-session.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gusnips/react",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.19",
|
|
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.
|
|
83
|
+
"@gusnips/http": "0.1.6",
|
|
84
84
|
"clsx": "^2.1.1",
|
|
85
85
|
"tailwind-merge": "^3.6.0"
|
|
86
86
|
},
|
package/src/query.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryClient, QueryObserver, type QueryObserverResult } from "@tanstack/react-query";
|
|
2
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
3
|
import { ApiError } from "./api-error.ts";
|
|
4
4
|
import { queryView, retryDelayMs, shouldRetry } from "./query.ts";
|
|
5
5
|
|
|
@@ -32,9 +32,10 @@ describe("shouldRetry", () => {
|
|
|
32
32
|
it("reads only its own ApiError as an answer", () => {
|
|
33
33
|
const vendor = Object.assign(new Error("Invalid login credentials"), { status: 400 });
|
|
34
34
|
expect(shouldRetry(vendor)).toBe(true);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
// The first backoff is at most 1.5 s, so 5 s would be the vendor's wait read as the server's.
|
|
36
|
+
expect(
|
|
37
|
+
retryDelayMs(0, Object.assign(new Error("x"), { status: 429, retryAfterSecs: 5 })),
|
|
38
|
+
).toBeLessThan(5000);
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
it("retries 5xx", () => {
|
|
@@ -135,6 +136,14 @@ describe("shouldRetry", () => {
|
|
|
135
136
|
});
|
|
136
137
|
|
|
137
138
|
describe("retryDelayMs", () => {
|
|
139
|
+
// The middle of the jitter, so the numbers below are the backoff itself.
|
|
140
|
+
beforeEach(() => {
|
|
141
|
+
vi.spyOn(Math, "random").mockReturnValue(0.5);
|
|
142
|
+
});
|
|
143
|
+
afterEach(() => {
|
|
144
|
+
vi.restoreAllMocks();
|
|
145
|
+
});
|
|
146
|
+
|
|
138
147
|
it("backs off exponentially when nothing said how long", () => {
|
|
139
148
|
expect(retryDelayMs(0, refusal(500))).toBe(1000);
|
|
140
149
|
expect(retryDelayMs(1, refusal(500))).toBe(2000);
|
package/src/query.ts
CHANGED
|
@@ -83,8 +83,8 @@ export function shouldRetry(
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
|
-
* How long before the next attempt: the server's stated wait when there is one,
|
|
87
|
-
*
|
|
86
|
+
* How long before the next attempt: the server's stated wait when there is one, an exponential
|
|
87
|
+
* backoff with jitter otherwise, and never less than the backoff — a `Retry-After: 0` is a
|
|
88
88
|
* server saying "immediately", which for a client that just got refused is still too soon.
|
|
89
89
|
*/
|
|
90
90
|
export function retryDelayMs(attemptIndex: number, error: unknown): number {
|
|
@@ -127,8 +127,9 @@ describe("isAuthOutage", () => {
|
|
|
127
127
|
// A gateway between us and GoTrue, which auth-js wraps by name.
|
|
128
128
|
expect(isAuthOutage(new AuthRetryableFetchError("Bad Gateway", 502))).toBe(true);
|
|
129
129
|
// And the reason the status clause is not redundant: the statuses earning that name are a
|
|
130
|
-
// LIST, so it has holes at every version. 507 and 599 are on no version of it, and
|
|
131
|
-
// as ordinary AuthApiErrors that `isAuthRetryableFetchError` answers false
|
|
130
|
+
// LIST, so it has holes at every version. 507 and 599 are on no version of it, and with a
|
|
131
|
+
// JSON body arrive as ordinary AuthApiErrors that `isAuthRetryableFetchError` answers false
|
|
132
|
+
// for. (With a body that is not JSON they arrive with no status at all: see below.)
|
|
132
133
|
expect(isAuthOutage(new AuthApiError("Insufficient Storage", 507, undefined))).toBe(true);
|
|
133
134
|
expect(isAuthOutage(new AuthApiError("Network Connect Timeout", 599, undefined))).toBe(true);
|
|
134
135
|
});
|
package/src/supabase-session.ts
CHANGED
|
@@ -34,8 +34,13 @@ type _SupabaseAuthFitsAdapter = Satisfied<
|
|
|
34
34
|
* whichever version happens to be installed, which is not the same as being right, and a fleet
|
|
35
35
|
* installs several versions at once. It is also a LIST rather than a range, so it has holes at
|
|
36
36
|
* every version, drift or no drift: at 2.112 nothing covers 505 through 519 or 531 up, and a
|
|
37
|
-
* 507 or a 599
|
|
38
|
-
*
|
|
37
|
+
* 507 or a 599 with a JSON body arrives as a plain `AuthApiError`. Pinning a recent SDK does not
|
|
38
|
+
* make the status clause redundant.
|
|
39
|
+
*
|
|
40
|
+
* The same statuses with a body that is NOT JSON — a proxy's HTML page — arrive as an
|
|
41
|
+
* `AuthUnknownError`, which carries no status at any status, so nothing here can tell that 507
|
|
42
|
+
* from a malformed 400. It answers false for both, on purpose: reading an unreadable 4xx as an
|
|
43
|
+
* outage would leave a dead session retrying forever, which is the other half of the same bug.
|
|
39
44
|
*
|
|
40
45
|
* Read the version a tree really serves with `bun why @supabase/auth-js`, which prints one
|
|
41
46
|
* heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
|