@gusnips/react 0.9.4 → 0.9.5

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/README.md CHANGED
@@ -75,6 +75,10 @@ anywhere that decision is made; the sentence you show is a separate question, an
75
75
  — "check your connection" is true of a request that never landed and false of a 502, which is
76
76
  ours. auth-js marks "nothing came back", and only that, with status 0.
77
77
 
78
+ It is safe to hand it the `error` from a `{ data, error }` result without checking it first:
79
+ `null` answers false. That is worth stating because `null` is the SUCCESS value of every
80
+ supabase-js auth call, so the obvious `if (isAuthOutage(error))` is written against it constantly.
81
+
78
82
  Supabase email links have two complete patterns. Keep either one, never half of each:
79
83
 
80
84
  - A link carrying `token_hash` needs one explicit `verifyOtp` call. Guard it against React
@@ -40,7 +40,8 @@ export interface SupabaseSessionAuth {
40
40
  * heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
41
41
  *
42
42
  * Anything that is not an auth error at all answers true: a failure from outside auth-js is not
43
- * a verdict on the credential either.
43
+ * a verdict on the credential either. Nothing at all answers false — `null` is what every
44
+ * supabase-js auth call returns on success, and success is not an outage.
44
45
  */
45
46
  export declare function isAuthOutage(error: unknown): boolean;
46
47
  /**
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAGpD;AAaD;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,cAAc,CAsBtF"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CASpD;AAaD;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,cAAc,CAsBtF"}
@@ -23,9 +23,17 @@ import { isAuthError, isAuthRetryableFetchError } from "@supabase/supabase-js";
23
23
  * heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
24
24
  *
25
25
  * Anything that is not an auth error at all answers true: a failure from outside auth-js is not
26
- * a verdict on the credential either.
26
+ * a verdict on the credential either. Nothing at all answers false — `null` is what every
27
+ * supabase-js auth call returns on success, and success is not an outage.
27
28
  */
28
29
  export function isAuthOutage(error) {
30
+ // Nothing thrown is not an outage, and this clause exists because the function is exported.
31
+ // `null` is the SUCCESS value of every supabase-js auth call, so the obvious
32
+ // `if (isAuthOutage(error))` around a `getUser()` result has to be safe; without this it read
33
+ // every success as auth being down. An adopter had already written that guard at its own call
34
+ // site, which is what a check missing from in here looks like from the outside.
35
+ if (error == null)
36
+ return false;
29
37
  if (!isAuthError(error))
30
38
  return true;
31
39
  return isAuthRetryableFetchError(error) || (error.status ?? 0) >= 500;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,yBAAyB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC;AACxE,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,0FAA0F;IAC1F,uFAAuF;IACvF,kFAAkF;IAClF,8EAA8E;IAC9E,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7D,8FAA8F;IAC9F,8FAA8F;IAC9F,OAAO,KAAK,CAAC,IAAI,KAAK,2BAA2B,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAyB;IACpE,OAAO;QACL,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,IAAI,CAAC;QAC5C,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpD,OAAO;oBACL,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,IAAI;oBACzC,WAAW,EAAE,KAAK,KAAK,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC;iBAClD,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,4FAA4F;IAC5F,6EAA6E;IAC7E,8FAA8F;IAC9F,8FAA8F;IAC9F,gFAAgF;IAChF,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,yBAAyB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC;AACxE,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,0FAA0F;IAC1F,uFAAuF;IACvF,kFAAkF;IAClF,8EAA8E;IAC9E,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC7D,8FAA8F;IAC9F,8FAA8F;IAC9F,OAAO,KAAK,CAAC,IAAI,KAAK,2BAA2B,CAAC;AACpD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAyB;IACpE,OAAO;QACL,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,IAAI,CAAC;QAC5C,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpD,OAAO;oBACL,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,IAAI,IAAI;oBACzC,WAAW,EAAE,KAAK,KAAK,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC;iBAClD,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,IAAI,KAAK;gBAAE,MAAM,KAAK,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gusnips/react",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
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",
@@ -2,6 +2,7 @@ import {
2
2
  AuthApiError,
3
3
  AuthRefreshDiscardedError,
4
4
  AuthRetryableFetchError,
5
+ AuthUnknownError,
5
6
  } from "@supabase/supabase-js";
6
7
  import { describe, expect, it, vi } from "vitest";
7
8
  import {
@@ -130,4 +131,26 @@ describe("isAuthOutage", () => {
130
131
  expect(isAuthOutage(new AuthApiError("Insufficient Storage", 507, undefined))).toBe(true);
131
132
  expect(isAuthOutage(new AuthApiError("Network Connect Timeout", 599, undefined))).toBe(true);
132
133
  });
134
+
135
+ it("reads nothing-went-wrong as nothing went wrong", () => {
136
+ // `null` is the SUCCESS value of every supabase-js auth call, and this function is
137
+ // exported, so the obvious `if (isAuthOutage(error))` around a `getUser()` result has to
138
+ // be safe. Before this, it answered true and put an outage on screen over every success.
139
+ // One adopter had already written the guard at its own call site, which is what a missing
140
+ // check in here looks like from the outside.
141
+ expect(isAuthOutage(null)).toBe(false);
142
+ expect(isAuthOutage(undefined)).toBe(false);
143
+ });
144
+
145
+ it("stays narrow for an error auth-js could not read", () => {
146
+ // AuthUnknownError is raised whenever the body does not parse as JSON, at ANY status, and
147
+ // it never fills one in — but `status` is still PRESENT, because the base class declares
148
+ // it, so `"status" in error` answers true and says nothing. That makes a 507 behind an
149
+ // HTML-answering proxy indistinguishable from a malformed 400, and the narrow answer is
150
+ // the right one: widening by class name would call the malformed 400 an outage too, and a
151
+ // dead session read as retryable is the same failure from the other side.
152
+ const unreadable = new AuthUnknownError("Unexpected token < in JSON", new Error("parse"));
153
+ expect(unreadable.status).toBeUndefined();
154
+ expect(isAuthOutage(unreadable)).toBe(false);
155
+ });
133
156
  });
@@ -41,9 +41,16 @@ type _SupabaseAuthFitsAdapter = Satisfied<
41
41
  * heading per RESOLVED version; `node_modules` keeps copies the resolver does not serve.
42
42
  *
43
43
  * Anything that is not an auth error at all answers true: a failure from outside auth-js is not
44
- * a verdict on the credential either.
44
+ * a verdict on the credential either. Nothing at all answers false — `null` is what every
45
+ * supabase-js auth call returns on success, and success is not an outage.
45
46
  */
46
47
  export function isAuthOutage(error: unknown): boolean {
48
+ // Nothing thrown is not an outage, and this clause exists because the function is exported.
49
+ // `null` is the SUCCESS value of every supabase-js auth call, so the obvious
50
+ // `if (isAuthOutage(error))` around a `getUser()` result has to be safe; without this it read
51
+ // every success as auth being down. An adopter had already written that guard at its own call
52
+ // site, which is what a check missing from in here looks like from the outside.
53
+ if (error == null) return false;
47
54
  if (!isAuthError(error)) return true;
48
55
  return isAuthRetryableFetchError(error) || (error.status ?? 0) >= 500;
49
56
  }