@molecule/app-http 1.2.0 → 1.3.0
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 +130 -18
- package/dist/auth-gate.d.ts +36 -22
- package/dist/auth-gate.d.ts.map +1 -1
- package/dist/auth-gate.js +118 -35
- package/dist/auth-gate.js.map +1 -1
- package/dist/errors.d.ts +67 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +75 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -7
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +9 -1
- package/dist/provider.js.map +1 -1
- package/dist/types.d.ts +47 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +37 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-10-
|
|
6
|
+
Generated: 2026-10-18T22:39:03.959Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/app-http
|
|
@@ -219,11 +219,15 @@ interface RequestConfig {
|
|
|
219
219
|
/**
|
|
220
220
|
* Send this request WITHOUT waiting for the session restore (the auth gate).
|
|
221
221
|
*
|
|
222
|
-
* A request the gate
|
|
223
|
-
*
|
|
224
|
-
* client
|
|
225
|
-
*
|
|
226
|
-
*
|
|
222
|
+
* A request the gate's restore issues from a LATER continuation must set this. The gate
|
|
223
|
+
* recognizes a request the settle function issues while it runs and never holds it — this
|
|
224
|
+
* package's client awaits the gate before anything else, so a `restoreSession()` that calls
|
|
225
|
+
* it directly does not deadlock. But a restore that awaits something else first
|
|
226
|
+
* (`await storage.get()`), then calls the client, reaches `awaitAuthGate` after that window:
|
|
227
|
+
* the gate then waits on itself, and every request on the page stalls until the gate times
|
|
228
|
+
* out (3 s) — so pass `skipAuthGate: true` on that request. A provider that awaits the gate
|
|
229
|
+
* inside a scheduled interceptor (the Axios bond) also reaches it after the window, so its
|
|
230
|
+
* restore's request needs the opt-out.
|
|
227
231
|
*
|
|
228
232
|
* ```typescript
|
|
229
233
|
* // the request the gate's restore makes, through the same client the gate holds back
|
|
@@ -232,7 +236,8 @@ interface RequestConfig {
|
|
|
232
236
|
*
|
|
233
237
|
* `@molecule/app-auth`'s own restore does not need it — it sends its request with
|
|
234
238
|
* `fetch`, not through this client. An app with its own session store that registers a
|
|
235
|
-
* gate with `setAuthGate` does
|
|
239
|
+
* gate with `setAuthGate` does not need it either when its restore calls the client
|
|
240
|
+
* directly.
|
|
236
241
|
*/
|
|
237
242
|
skipAuthGate?: boolean
|
|
238
243
|
|
|
@@ -396,14 +401,38 @@ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTION
|
|
|
396
401
|
|
|
397
402
|
HTTP error with response details.
|
|
398
403
|
|
|
404
|
+
**`status` is an HTTP status when the server answered, and `0` when it did not.**
|
|
405
|
+
A `0` means NO response exists: the request was aborted (an `AbortController`, a
|
|
406
|
+
component's effect cleanup, a route change tearing the request down) or the
|
|
407
|
+
network failed before anything came back. It is not an HTTP status at all, so it
|
|
408
|
+
says nothing about the session — an app must never treat `status < 500` as
|
|
409
|
+
"signed out", because every aborted request on a route change would clear the
|
|
410
|
+
session. The correct check is {@link isAuthFailure} (`status === 401 || status === 403`);
|
|
411
|
+
`isNoResponse` (`status === 0`) identifies this case.
|
|
412
|
+
|
|
399
413
|
```typescript
|
|
400
414
|
class HttpError extends Error {
|
|
415
|
+
/**
|
|
416
|
+
* Builds a failed-request error.
|
|
417
|
+
*
|
|
418
|
+
* @param message - Human-readable message (already translated where a key exists).
|
|
419
|
+
* @param status - HTTP status, or `0` when no response was received (aborted / network failure).
|
|
420
|
+
* @param response - Parsed response when the server answered, otherwise undefined.
|
|
421
|
+
* @param config - The request config that failed.
|
|
422
|
+
* @param errorKey - Translation key for the failure (`http.error.aborted` for an
|
|
423
|
+
* aborted request, `http.error.networkError` for a real network failure).
|
|
424
|
+
* @param aborted - Whether the request was aborted before a response: an
|
|
425
|
+
* `AbortController` signal (component cleanup, a cancelled request) or the
|
|
426
|
+
* browser tearing the fetch down during a navigation. Distinguishes an abort
|
|
427
|
+
* from a network outage on the same `status === 0`, without parsing the message.
|
|
428
|
+
*/
|
|
401
429
|
constructor(
|
|
402
430
|
message: string,
|
|
403
431
|
public status: number,
|
|
404
432
|
public response?: HttpResponse,
|
|
405
433
|
public config?: FullRequestConfig,
|
|
406
434
|
public errorKey?: string,
|
|
435
|
+
public aborted = false,
|
|
407
436
|
) {
|
|
408
437
|
super(message)
|
|
409
438
|
this.name = 'HttpError'
|
|
@@ -423,10 +452,20 @@ template auth that is `() => authClient.whenRestored()`, which resolves
|
|
|
423
452
|
immediately when no restore is in flight, so registering it never makes a
|
|
424
453
|
request wait longer than the restore it was about to race anyway.
|
|
425
454
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
(
|
|
429
|
-
|
|
455
|
+
Waiting for the restore does NOT attach its token: a separately created HTTP
|
|
456
|
+
client needs `createDefaultHttpClientWithAuthBearer({ baseURL,
|
|
457
|
+
getToken: () => authClient.getAccessToken(), authScheme })` from
|
|
458
|
+
`@molecule/app-bonds-default-react` (or the auth client built with
|
|
459
|
+
`createDefaultAuthClientWithHttpSync`, which mirrors the token into the
|
|
460
|
+
bonded client) plus `setAuthGate(() => authClient.whenRestored())`.
|
|
461
|
+
|
|
462
|
+
The restore's own requests are never held: a request the settle function issues while it
|
|
463
|
+
runs goes out immediately, so `setAuthGate(() => restoreSession())` cannot deadlock even
|
|
464
|
+
when `restoreSession` calls the gated client. A restore that awaits something else first
|
|
465
|
+
(a storage read, a `Promise.resolve()`) issues its request from a later continuation, which
|
|
466
|
+
the gate cannot recognize — that request needs `skipAuthGate: true` (see
|
|
467
|
+
`RequestConfig.skipAuthGate`). `@molecule/app-auth`'s own restore needs neither because it
|
|
468
|
+
uses `fetch` rather than the bonded client.
|
|
430
469
|
|
|
431
470
|
```typescript
|
|
432
471
|
function setAuthGate(next: (() => Promise<void>) | null): void
|
|
@@ -453,6 +492,66 @@ function awaitAuthGate(request?: AuthGateRequest): Promise<void>
|
|
|
453
492
|
|
|
454
493
|
**Returns:** A promise that settles when the gate has released the request.
|
|
455
494
|
|
|
495
|
+
#### `isHttpError(err)`
|
|
496
|
+
|
|
497
|
+
Whether `err` is an {@link HttpError} from this package.
|
|
498
|
+
|
|
499
|
+
```typescript
|
|
500
|
+
function isHttpError(err: unknown): boolean
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
- `err` — Any thrown value.
|
|
504
|
+
|
|
505
|
+
**Returns:** True for an `HttpError`.
|
|
506
|
+
|
|
507
|
+
#### `isAuthFailure(err)`
|
|
508
|
+
|
|
509
|
+
Whether the server REJECTED the request's credential — the only failure that
|
|
510
|
+
justifies clearing a session.
|
|
511
|
+
|
|
512
|
+
`401` (unauthenticated/expired token) and `403` (authenticated but refused) are
|
|
513
|
+
the two statuses that say "this credential no longer authorizes this session".
|
|
514
|
+
Everything else — `0` (aborted or offline), `404` (wrong endpoint), `5xx` (server
|
|
515
|
+
fault), a rate limit — says nothing about the credential.
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
function isAuthFailure(err: unknown): boolean
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
- `err` — Any thrown value.
|
|
522
|
+
|
|
523
|
+
**Returns:** True only when `err` is an `HttpError` with status 401 or 403.
|
|
524
|
+
|
|
525
|
+
#### `isNoResponse(err)`
|
|
526
|
+
|
|
527
|
+
Whether no response was received at all: the request was aborted or the network
|
|
528
|
+
failed. `status === 0` is not an HTTP status — it must never be read as
|
|
529
|
+
"the user is not signed in".
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
function isNoResponse(err: unknown): boolean
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
- `err` — Any thrown value.
|
|
536
|
+
|
|
537
|
+
**Returns:** True when `err` is an `HttpError` with status `0`.
|
|
538
|
+
|
|
539
|
+
#### `isAborted(err)`
|
|
540
|
+
|
|
541
|
+
Whether the request was ABORTED (an `AbortController` signal, or the browser
|
|
542
|
+
cancelling the fetch during a navigation) rather than failing on the network.
|
|
543
|
+
|
|
544
|
+
Both arrive as `status === 0`; this distinguishes them, so a UI can stay silent
|
|
545
|
+
for a cancelled request while still reporting a real outage.
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
function isAborted(err: unknown): boolean
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
- `err` — Any thrown value.
|
|
552
|
+
|
|
553
|
+
**Returns:** True when `err` is an `HttpError` flagged `aborted`.
|
|
554
|
+
|
|
456
555
|
#### `createFetchClient(config)`
|
|
457
556
|
|
|
458
557
|
Creates a fetch-based HTTP client using the native Fetch API.
|
|
@@ -726,13 +825,26 @@ authScheme })` from `@molecule/app-bonds-default-react` (or an auth client built
|
|
|
726
825
|
`createDefaultAuthClientWithHttpSync`, which mirrors the token into the bonded client), because
|
|
727
826
|
`setAuthGate` alone sends no `Authorization` header.
|
|
728
827
|
|
|
729
|
-
**
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
`http.get(currentUserEndpoint, {
|
|
735
|
-
|
|
828
|
+
**The gate never holds its own restore's request.** A request the settle function issues
|
|
829
|
+
while it runs (its call reaches this client before the function awaits anything) is part of
|
|
830
|
+
the restore it is waiting for, so it goes out immediately — `setAuthGate(() =>
|
|
831
|
+
restoreSession())` does not deadlock even when `restoreSession` uses this client. A restore
|
|
832
|
+
that awaits something else first and only then calls the client reaches it after that
|
|
833
|
+
window, and that request must opt out of the gate: `http.get(currentUserEndpoint, {
|
|
834
|
+
skipAuthGate: true })`. Without the opt-out the gate waits on itself, the restore never
|
|
835
|
+
settles, and every request the gate holds stalls until it times out (3 s).
|
|
836
|
+
`@molecule/app-auth`'s own restore does not need it (it calls `fetch`, not this client).
|
|
837
|
+
|
|
838
|
+
**A failed request's `status` is `0` when NO response arrived — never read it as
|
|
839
|
+
"signed out".** An aborted request (an `AbortController` signal, a component's
|
|
840
|
+
effect cleanup, a route change tearing the fetch down) and a network outage both
|
|
841
|
+
throw an `HttpError` with `status === 0`; the aborted ones also carry
|
|
842
|
+
`aborted: true` and the `http.error.aborted` key, the rest `http.error.networkError`.
|
|
843
|
+
Neither says anything about the session. To decide whether a session ended, use
|
|
844
|
+
`isAuthFailure(err)` (401/403 only); `isNoResponse(err)` identifies the no-response
|
|
845
|
+
case so a caller can stay silent instead of reporting an outage. **Do not write
|
|
846
|
+
`err instanceof HttpError && err.status < 500` as a sign-out check** — it clears
|
|
847
|
+
the session on every aborted navigation request.
|
|
736
848
|
|
|
737
849
|
## Translations
|
|
738
850
|
|
package/dist/auth-gate.d.ts
CHANGED
|
@@ -27,24 +27,28 @@
|
|
|
27
27
|
* `setupHttpDefault()`), and a gate installed on the throwaway client the auth
|
|
28
28
|
* bond saw would be silently lost.
|
|
29
29
|
*
|
|
30
|
-
* ##
|
|
31
|
-
*
|
|
32
|
-
* `awaitAuthGate` holds every request while the gate is pending —
|
|
33
|
-
*
|
|
34
|
-
* the
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* and
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
30
|
+
* ## The gate's own restore requests are never held
|
|
31
|
+
*
|
|
32
|
+
* `awaitAuthGate` holds every request while the gate is pending — except the ones the gate's
|
|
33
|
+
* settle function issues itself. Those are part of the restore it is waiting for; holding them
|
|
34
|
+
* makes the gate wait on itself, and nothing but the timeout releases anything (X1
|
|
35
|
+
* xr-molecule-flash-m97 and xr-molecule-flash-m173 both lost minutes to this: an app
|
|
36
|
+
* registering `setAuthGate(() => restoreSession())` over a restore that fetched through the
|
|
37
|
+
* same client, every page held for the full bound, and 917 `GET /api/user` requests named by
|
|
38
|
+
* one console line). So `setAuthGate(() => restoreSession())` works as written when
|
|
39
|
+
* `restoreSession` calls the gated client.
|
|
40
|
+
*
|
|
41
|
+
* "Issued by the gate" means issued while the settle function is running: this package's
|
|
42
|
+
* fetch client awaits the gate before anything else, so a restore's call is made in the settle
|
|
43
|
+
* function's own synchronous execution. A restore that awaits something else first (a storage
|
|
44
|
+
* read, a `Promise.resolve()`) and only then calls the client issues its request from a later
|
|
45
|
+
* continuation, which nothing can attribute to the gate — browsers ship no async-context API
|
|
46
|
+
* (`AsyncContext`/`AsyncLocalStorage`) to ask, and releasing requests merely because the gate is
|
|
47
|
+
* pending would drop exactly the first-paint requests the gate exists to hold (m95). A provider
|
|
48
|
+
* whose request pipeline awaits the gate in a scheduled interceptor (the Axios bond) reaches it
|
|
49
|
+
* a microtask after the settle function returns, outside the window, for the same reason. Such a
|
|
50
|
+
* request must pass `skipAuthGate: true` (`RequestConfig.skipAuthGate`), and a timeout with
|
|
51
|
+
* requests held is reported at error level naming it.
|
|
48
52
|
*
|
|
49
53
|
* @module
|
|
50
54
|
*/
|
|
@@ -58,10 +62,20 @@ import type { AuthGateRequest } from './types.js';
|
|
|
58
62
|
* immediately when no restore is in flight, so registering it never makes a
|
|
59
63
|
* request wait longer than the restore it was about to race anyway.
|
|
60
64
|
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* (
|
|
64
|
-
*
|
|
65
|
+
* Waiting for the restore does NOT attach its token: a separately created HTTP
|
|
66
|
+
* client needs `createDefaultHttpClientWithAuthBearer({ baseURL,
|
|
67
|
+
* getToken: () => authClient.getAccessToken(), authScheme })` from
|
|
68
|
+
* `@molecule/app-bonds-default-react` (or the auth client built with
|
|
69
|
+
* `createDefaultAuthClientWithHttpSync`, which mirrors the token into the
|
|
70
|
+
* bonded client) plus `setAuthGate(() => authClient.whenRestored())`.
|
|
71
|
+
*
|
|
72
|
+
* The restore's own requests are never held: a request the settle function issues while it
|
|
73
|
+
* runs goes out immediately, so `setAuthGate(() => restoreSession())` cannot deadlock even
|
|
74
|
+
* when `restoreSession` calls the gated client. A restore that awaits something else first
|
|
75
|
+
* (a storage read, a `Promise.resolve()`) issues its request from a later continuation, which
|
|
76
|
+
* the gate cannot recognize — that request needs `skipAuthGate: true` (see
|
|
77
|
+
* `RequestConfig.skipAuthGate`). `@molecule/app-auth`'s own restore needs neither because it
|
|
78
|
+
* uses `fetch` rather than the bonded client.
|
|
65
79
|
*
|
|
66
80
|
* @param next - The gate, or `null` to clear a previously registered one.
|
|
67
81
|
*
|
package/dist/auth-gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-gate.d.ts","sourceRoot":"","sources":["../src/auth-gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-gate.d.ts","sourceRoot":"","sources":["../src/auth-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAkEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAG,IAIhE,CAAA;AA8ED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,GAAU,UAAU,eAAe,KAAG,OAAO,CAAC,IAAI,CAwC3E,CAAA"}
|
package/dist/auth-gate.js
CHANGED
|
@@ -27,24 +27,28 @@
|
|
|
27
27
|
* `setupHttpDefault()`), and a gate installed on the throwaway client the auth
|
|
28
28
|
* bond saw would be silently lost.
|
|
29
29
|
*
|
|
30
|
-
* ##
|
|
31
|
-
*
|
|
32
|
-
* `awaitAuthGate` holds every request while the gate is pending —
|
|
33
|
-
*
|
|
34
|
-
* the
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* and
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
30
|
+
* ## The gate's own restore requests are never held
|
|
31
|
+
*
|
|
32
|
+
* `awaitAuthGate` holds every request while the gate is pending — except the ones the gate's
|
|
33
|
+
* settle function issues itself. Those are part of the restore it is waiting for; holding them
|
|
34
|
+
* makes the gate wait on itself, and nothing but the timeout releases anything (X1
|
|
35
|
+
* xr-molecule-flash-m97 and xr-molecule-flash-m173 both lost minutes to this: an app
|
|
36
|
+
* registering `setAuthGate(() => restoreSession())` over a restore that fetched through the
|
|
37
|
+
* same client, every page held for the full bound, and 917 `GET /api/user` requests named by
|
|
38
|
+
* one console line). So `setAuthGate(() => restoreSession())` works as written when
|
|
39
|
+
* `restoreSession` calls the gated client.
|
|
40
|
+
*
|
|
41
|
+
* "Issued by the gate" means issued while the settle function is running: this package's
|
|
42
|
+
* fetch client awaits the gate before anything else, so a restore's call is made in the settle
|
|
43
|
+
* function's own synchronous execution. A restore that awaits something else first (a storage
|
|
44
|
+
* read, a `Promise.resolve()`) and only then calls the client issues its request from a later
|
|
45
|
+
* continuation, which nothing can attribute to the gate — browsers ship no async-context API
|
|
46
|
+
* (`AsyncContext`/`AsyncLocalStorage`) to ask, and releasing requests merely because the gate is
|
|
47
|
+
* pending would drop exactly the first-paint requests the gate exists to hold (m95). A provider
|
|
48
|
+
* whose request pipeline awaits the gate in a scheduled interceptor (the Axios bond) reaches it
|
|
49
|
+
* a microtask after the settle function returns, outside the window, for the same reason. Such a
|
|
50
|
+
* request must pass `skipAuthGate: true` (`RequestConfig.skipAuthGate`), and a timeout with
|
|
51
|
+
* requests held is reported at error level naming it.
|
|
48
52
|
*
|
|
49
53
|
* @module
|
|
50
54
|
*/
|
|
@@ -66,6 +70,25 @@ const heldRequests = new Map();
|
|
|
66
70
|
* gates. Cleared when the same gate later releases a request normally.
|
|
67
71
|
*/
|
|
68
72
|
let reportedStall = null;
|
|
73
|
+
/**
|
|
74
|
+
* The settle-function invocation requests are currently waiting on, shared by every request
|
|
75
|
+
* that arrives while the gate is pending.
|
|
76
|
+
*
|
|
77
|
+
* Without it each held request re-invokes the gate, and a gate that issues a request on every
|
|
78
|
+
* call floods the network: the m97 shape measured 855 `fetch` calls for one page (`task-auth-
|
|
79
|
+
* gate-deadlock.report.md`). `null` when no invocation is in flight; `setAuthGate` clears it
|
|
80
|
+
* so a re-registered gate is never shared with the old one's waiters.
|
|
81
|
+
*/
|
|
82
|
+
let inFlightGate = null;
|
|
83
|
+
/**
|
|
84
|
+
* True only while the gate's settle function is executing synchronously.
|
|
85
|
+
*
|
|
86
|
+
* A request that reaches `awaitAuthGate` in this window was issued BY the restore — the fetch
|
|
87
|
+
* client's `request()` awaits the gate before anything else, so the call is made in the settle
|
|
88
|
+
* function's own execution. Holding it would make the gate wait on itself (see the module
|
|
89
|
+
* doc); requests issued after the function awaits something else are held as usual.
|
|
90
|
+
*/
|
|
91
|
+
let gateSettling = false;
|
|
69
92
|
/**
|
|
70
93
|
* How long a request may be held by the gate before it is sent anyway.
|
|
71
94
|
*
|
|
@@ -96,10 +119,20 @@ const GATE_TIMEOUT_MS = 3_000;
|
|
|
96
119
|
* immediately when no restore is in flight, so registering it never makes a
|
|
97
120
|
* request wait longer than the restore it was about to race anyway.
|
|
98
121
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* (
|
|
102
|
-
*
|
|
122
|
+
* Waiting for the restore does NOT attach its token: a separately created HTTP
|
|
123
|
+
* client needs `createDefaultHttpClientWithAuthBearer({ baseURL,
|
|
124
|
+
* getToken: () => authClient.getAccessToken(), authScheme })` from
|
|
125
|
+
* `@molecule/app-bonds-default-react` (or the auth client built with
|
|
126
|
+
* `createDefaultAuthClientWithHttpSync`, which mirrors the token into the
|
|
127
|
+
* bonded client) plus `setAuthGate(() => authClient.whenRestored())`.
|
|
128
|
+
*
|
|
129
|
+
* The restore's own requests are never held: a request the settle function issues while it
|
|
130
|
+
* runs goes out immediately, so `setAuthGate(() => restoreSession())` cannot deadlock even
|
|
131
|
+
* when `restoreSession` calls the gated client. A restore that awaits something else first
|
|
132
|
+
* (a storage read, a `Promise.resolve()`) issues its request from a later continuation, which
|
|
133
|
+
* the gate cannot recognize — that request needs `skipAuthGate: true` (see
|
|
134
|
+
* `RequestConfig.skipAuthGate`). `@molecule/app-auth`'s own restore needs neither because it
|
|
135
|
+
* uses `fetch` rather than the bonded client.
|
|
103
136
|
*
|
|
104
137
|
* @param next - The gate, or `null` to clear a previously registered one.
|
|
105
138
|
*
|
|
@@ -112,6 +145,7 @@ const GATE_TIMEOUT_MS = 3_000;
|
|
|
112
145
|
*/
|
|
113
146
|
export const setAuthGate = (next) => {
|
|
114
147
|
gate = next;
|
|
148
|
+
inFlightGate = null;
|
|
115
149
|
reportedStall = null;
|
|
116
150
|
};
|
|
117
151
|
/**
|
|
@@ -121,21 +155,69 @@ export const setAuthGate = (next) => {
|
|
|
121
155
|
const describeRequest = (request) => request?.method || request?.url
|
|
122
156
|
? `${request?.method ?? 'GET'} ${request?.url ?? ''}`.trim()
|
|
123
157
|
: 'a request';
|
|
158
|
+
/**
|
|
159
|
+
* How many held request names the stalled-gate report prints before summarizing the rest.
|
|
160
|
+
*
|
|
161
|
+
* The report is console output, and every reader of it truncates: molecule-dev's route walk
|
|
162
|
+
* keeps the first 200 characters of a console error, so the sentence naming the fix has to
|
|
163
|
+
* come first — and the request list is capped so the message stays readable when a deadlocked
|
|
164
|
+
* gate has held hundreds of requests (xr-molecule-flash-m173: 917 `GET /api/user`).
|
|
165
|
+
*/
|
|
166
|
+
const MAX_NAMED_HELD_REQUESTS = 5;
|
|
124
167
|
/**
|
|
125
168
|
* Reports a gate that timed out while holding requests: once per stuck gate, at error level
|
|
126
169
|
* so it reaches the page's error console and any error transport — a console warning on a
|
|
127
170
|
* deployed URL reads as "the site is slow", which is what the gate itself was added for.
|
|
171
|
+
*
|
|
172
|
+
* Leads with the cause and the fix, then names at most `MAX_NAMED_HELD_REQUESTS` distinct
|
|
173
|
+
* requests and counts the rest: an unbounded join buried the fix clause behind 900 names in
|
|
174
|
+
* xr-molecule-flash-m173, and no reader of the line ever reached it.
|
|
128
175
|
*/
|
|
129
176
|
const reportStalledGate = (stuck) => {
|
|
130
177
|
if (reportedStall === stuck)
|
|
131
178
|
return;
|
|
132
179
|
reportedStall = stuck;
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
`
|
|
138
|
-
|
|
180
|
+
const names = [...new Set(heldRequests.values())];
|
|
181
|
+
const shown = names.slice(0, MAX_NAMED_HELD_REQUESTS);
|
|
182
|
+
const more = heldRequests.size - shown.length;
|
|
183
|
+
logger.error(`The auth gate is waiting on itself: its restore's request is held by it. Send that ` +
|
|
184
|
+
`request with \`skipAuthGate: true\`, or clear the gate with \`setAuthGate(null)\` if ` +
|
|
185
|
+
`nothing restores a session. Held ${heldRequests.size} request(s) for ` +
|
|
186
|
+
`${GATE_TIMEOUT_MS}ms${shown.length ? `: ${shown.join(', ')}` : ''}` +
|
|
187
|
+
`${more > 0 ? ` (and ${more} more)` : ''}.`);
|
|
188
|
+
};
|
|
189
|
+
/**
|
|
190
|
+
* Starts the gate's settle function — once, shared by every request that arrives while it is
|
|
191
|
+
* pending — turning a rejection (or a synchronous throw) into a logged warning so a failed
|
|
192
|
+
* restore releases its waiters instead of rejecting them.
|
|
193
|
+
*
|
|
194
|
+
* `gateSettling` is true only for the function's synchronous execution: the IIFE runs
|
|
195
|
+
* `current()` up to its first `await` before this call returns, and any request the restore
|
|
196
|
+
* issues there (the gated client's `request()` awaits the gate before anything else) bypasses
|
|
197
|
+
* the gate instead of waiting on the invocation it belongs to.
|
|
198
|
+
*/
|
|
199
|
+
const invokeGate = (current) => {
|
|
200
|
+
if (inFlightGate)
|
|
201
|
+
return inFlightGate;
|
|
202
|
+
let invocation;
|
|
203
|
+
gateSettling = true;
|
|
204
|
+
try {
|
|
205
|
+
invocation = (async () => current())();
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
gateSettling = false;
|
|
209
|
+
}
|
|
210
|
+
const shared = invocation.catch((error) => {
|
|
211
|
+
logger.warn('The auth gate rejected; sending the request without waiting for it', {
|
|
212
|
+
error,
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
inFlightGate = shared;
|
|
216
|
+
void shared.then(() => {
|
|
217
|
+
if (inFlightGate === shared)
|
|
218
|
+
inFlightGate = null;
|
|
219
|
+
});
|
|
220
|
+
return shared;
|
|
139
221
|
};
|
|
140
222
|
/**
|
|
141
223
|
* Awaits the registered gate, if any. Every HTTP provider calls this before it
|
|
@@ -160,19 +242,20 @@ export const awaitAuthGate = async (request) => {
|
|
|
160
242
|
const current = gate;
|
|
161
243
|
if (!current)
|
|
162
244
|
return;
|
|
245
|
+
// Issued while the gate's settle function is running: part of the restore it is settling,
|
|
246
|
+
// never held by it. See `invokeGate` and the module doc.
|
|
247
|
+
if (gateSettling)
|
|
248
|
+
return;
|
|
163
249
|
const token = Symbol('held-request');
|
|
164
250
|
heldRequests.set(token, describeRequest(request));
|
|
165
251
|
let timer;
|
|
166
252
|
let timedOut = false;
|
|
167
253
|
try {
|
|
168
254
|
await Promise.race([
|
|
169
|
-
//
|
|
170
|
-
// a gate is someone else's code, and no shape of it may reject the
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
error,
|
|
174
|
-
});
|
|
175
|
-
}),
|
|
255
|
+
// One invocation, shared: `invokeGate` also turns a gate that throws SYNCHRONOUSLY into
|
|
256
|
+
// a rejection — a gate is someone else's code, and no shape of it may reject the
|
|
257
|
+
// request it was holding.
|
|
258
|
+
invokeGate(current),
|
|
176
259
|
new Promise((resolve) => {
|
|
177
260
|
timer = setTimeout(() => {
|
|
178
261
|
timedOut = true;
|
package/dist/auth-gate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-gate.js","sourceRoot":"","sources":["../src/auth-gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth-gate.js","sourceRoot":"","sources":["../src/auth-gate.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify a failed request instead of reading its `status` by hand.
|
|
3
|
+
*
|
|
4
|
+
* A failure from this package is an {@link HttpError} whose `status` is either an
|
|
5
|
+
* HTTP status (the server answered) or `0` (it did not — the request was aborted or
|
|
6
|
+
* the network failed). Code that clears a session must ask "did the server REJECT
|
|
7
|
+
* the credential?", which is `status === 401 || status === 403` and nothing else:
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* try {
|
|
11
|
+
* await http.get('/projects')
|
|
12
|
+
* } catch (err) {
|
|
13
|
+
* if (isAuthFailure(err)) clearSession()
|
|
14
|
+
* else if (isNoResponse(err)) return // aborted / offline — keep the session
|
|
15
|
+
* else showError(err)
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* `err instanceof HttpError && err.status < 500` is the trap these helpers exist to
|
|
20
|
+
* replace: an aborted request (a component unmounting, a route change cancelling an
|
|
21
|
+
* in-flight fetch) and a network outage both arrive with `status === 0`, so that
|
|
22
|
+
* check signs the user out on every navigation that cancels a request.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import { HttpError } from './types.js';
|
|
27
|
+
/**
|
|
28
|
+
* Whether `err` is an {@link HttpError} from this package.
|
|
29
|
+
*
|
|
30
|
+
* @param err - Any thrown value.
|
|
31
|
+
* @returns True for an `HttpError`.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isHttpError(err: unknown): err is HttpError;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the server REJECTED the request's credential — the only failure that
|
|
36
|
+
* justifies clearing a session.
|
|
37
|
+
*
|
|
38
|
+
* `401` (unauthenticated/expired token) and `403` (authenticated but refused) are
|
|
39
|
+
* the two statuses that say "this credential no longer authorizes this session".
|
|
40
|
+
* Everything else — `0` (aborted or offline), `404` (wrong endpoint), `5xx` (server
|
|
41
|
+
* fault), a rate limit — says nothing about the credential.
|
|
42
|
+
*
|
|
43
|
+
* @param err - Any thrown value.
|
|
44
|
+
* @returns True only when `err` is an `HttpError` with status 401 or 403.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isAuthFailure(err: unknown): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether no response was received at all: the request was aborted or the network
|
|
49
|
+
* failed. `status === 0` is not an HTTP status — it must never be read as
|
|
50
|
+
* "the user is not signed in".
|
|
51
|
+
*
|
|
52
|
+
* @param err - Any thrown value.
|
|
53
|
+
* @returns True when `err` is an `HttpError` with status `0`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isNoResponse(err: unknown): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Whether the request was ABORTED (an `AbortController` signal, or the browser
|
|
58
|
+
* cancelling the fetch during a navigation) rather than failing on the network.
|
|
59
|
+
*
|
|
60
|
+
* Both arrive as `status === 0`; this distinguishes them, so a UI can stay silent
|
|
61
|
+
* for a cancelled request while still reporting a real outage.
|
|
62
|
+
*
|
|
63
|
+
* @param err - Any thrown value.
|
|
64
|
+
* @returns True when `err` is an `HttpError` flagged `aborted`.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isAborted(err: unknown): boolean;
|
|
67
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,SAAS,CAE1D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAEnD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAE/C"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify a failed request instead of reading its `status` by hand.
|
|
3
|
+
*
|
|
4
|
+
* A failure from this package is an {@link HttpError} whose `status` is either an
|
|
5
|
+
* HTTP status (the server answered) or `0` (it did not — the request was aborted or
|
|
6
|
+
* the network failed). Code that clears a session must ask "did the server REJECT
|
|
7
|
+
* the credential?", which is `status === 401 || status === 403` and nothing else:
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* try {
|
|
11
|
+
* await http.get('/projects')
|
|
12
|
+
* } catch (err) {
|
|
13
|
+
* if (isAuthFailure(err)) clearSession()
|
|
14
|
+
* else if (isNoResponse(err)) return // aborted / offline — keep the session
|
|
15
|
+
* else showError(err)
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* `err instanceof HttpError && err.status < 500` is the trap these helpers exist to
|
|
20
|
+
* replace: an aborted request (a component unmounting, a route change cancelling an
|
|
21
|
+
* in-flight fetch) and a network outage both arrive with `status === 0`, so that
|
|
22
|
+
* check signs the user out on every navigation that cancels a request.
|
|
23
|
+
*
|
|
24
|
+
* @module
|
|
25
|
+
*/
|
|
26
|
+
import { HttpError } from './types.js';
|
|
27
|
+
/**
|
|
28
|
+
* Whether `err` is an {@link HttpError} from this package.
|
|
29
|
+
*
|
|
30
|
+
* @param err - Any thrown value.
|
|
31
|
+
* @returns True for an `HttpError`.
|
|
32
|
+
*/
|
|
33
|
+
export function isHttpError(err) {
|
|
34
|
+
return err instanceof HttpError;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether the server REJECTED the request's credential — the only failure that
|
|
38
|
+
* justifies clearing a session.
|
|
39
|
+
*
|
|
40
|
+
* `401` (unauthenticated/expired token) and `403` (authenticated but refused) are
|
|
41
|
+
* the two statuses that say "this credential no longer authorizes this session".
|
|
42
|
+
* Everything else — `0` (aborted or offline), `404` (wrong endpoint), `5xx` (server
|
|
43
|
+
* fault), a rate limit — says nothing about the credential.
|
|
44
|
+
*
|
|
45
|
+
* @param err - Any thrown value.
|
|
46
|
+
* @returns True only when `err` is an `HttpError` with status 401 or 403.
|
|
47
|
+
*/
|
|
48
|
+
export function isAuthFailure(err) {
|
|
49
|
+
return isHttpError(err) && (err.status === 401 || err.status === 403);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Whether no response was received at all: the request was aborted or the network
|
|
53
|
+
* failed. `status === 0` is not an HTTP status — it must never be read as
|
|
54
|
+
* "the user is not signed in".
|
|
55
|
+
*
|
|
56
|
+
* @param err - Any thrown value.
|
|
57
|
+
* @returns True when `err` is an `HttpError` with status `0`.
|
|
58
|
+
*/
|
|
59
|
+
export function isNoResponse(err) {
|
|
60
|
+
return isHttpError(err) && err.status === 0;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether the request was ABORTED (an `AbortController` signal, or the browser
|
|
64
|
+
* cancelling the fetch during a navigation) rather than failing on the network.
|
|
65
|
+
*
|
|
66
|
+
* Both arrive as `status === 0`; this distinguishes them, so a UI can stay silent
|
|
67
|
+
* for a cancelled request while still reporting a real outage.
|
|
68
|
+
*
|
|
69
|
+
* @param err - Any thrown value.
|
|
70
|
+
* @returns True when `err` is an `HttpError` flagged `aborted`.
|
|
71
|
+
*/
|
|
72
|
+
export function isAborted(err) {
|
|
73
|
+
return isHttpError(err) && err.aborted;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,OAAO,GAAG,YAAY,SAAS,CAAA;AACjC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,CAAA;AACvE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,CAAA;AAC7C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,CAAA;AACxC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -78,18 +78,32 @@
|
|
|
78
78
|
* `createDefaultAuthClientWithHttpSync`, which mirrors the token into the bonded client), because
|
|
79
79
|
* `setAuthGate` alone sends no `Authorization` header.
|
|
80
80
|
*
|
|
81
|
-
* **
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* `http.get(currentUserEndpoint, {
|
|
87
|
-
*
|
|
81
|
+
* **The gate never holds its own restore's request.** A request the settle function issues
|
|
82
|
+
* while it runs (its call reaches this client before the function awaits anything) is part of
|
|
83
|
+
* the restore it is waiting for, so it goes out immediately — `setAuthGate(() =>
|
|
84
|
+
* restoreSession())` does not deadlock even when `restoreSession` uses this client. A restore
|
|
85
|
+
* that awaits something else first and only then calls the client reaches it after that
|
|
86
|
+
* window, and that request must opt out of the gate: `http.get(currentUserEndpoint, {
|
|
87
|
+
* skipAuthGate: true })`. Without the opt-out the gate waits on itself, the restore never
|
|
88
|
+
* settles, and every request the gate holds stalls until it times out (3 s).
|
|
89
|
+
* `@molecule/app-auth`'s own restore does not need it (it calls `fetch`, not this client).
|
|
90
|
+
*
|
|
91
|
+
* **A failed request's `status` is `0` when NO response arrived — never read it as
|
|
92
|
+
* "signed out".** An aborted request (an `AbortController` signal, a component's
|
|
93
|
+
* effect cleanup, a route change tearing the fetch down) and a network outage both
|
|
94
|
+
* throw an `HttpError` with `status === 0`; the aborted ones also carry
|
|
95
|
+
* `aborted: true` and the `http.error.aborted` key, the rest `http.error.networkError`.
|
|
96
|
+
* Neither says anything about the session. To decide whether a session ended, use
|
|
97
|
+
* `isAuthFailure(err)` (401/403 only); `isNoResponse(err)` identifies the no-response
|
|
98
|
+
* case so a caller can stay silent instead of reporting an outage. **Do not write
|
|
99
|
+
* `err instanceof HttpError && err.status < 500` as a sign-out check** — it clears
|
|
100
|
+
* the session on every aborted navigation request.
|
|
88
101
|
*
|
|
89
102
|
* @module
|
|
90
103
|
*/
|
|
91
104
|
export * from './auth-gate.js';
|
|
92
105
|
export * from './client.js';
|
|
106
|
+
export * from './errors.js';
|
|
93
107
|
export * from './interceptors.js';
|
|
94
108
|
export * from './provider.js';
|
|
95
109
|
export * from './types.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGG;AAEH,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -78,18 +78,32 @@
|
|
|
78
78
|
* `createDefaultAuthClientWithHttpSync`, which mirrors the token into the bonded client), because
|
|
79
79
|
* `setAuthGate` alone sends no `Authorization` header.
|
|
80
80
|
*
|
|
81
|
-
* **
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* `http.get(currentUserEndpoint, {
|
|
87
|
-
*
|
|
81
|
+
* **The gate never holds its own restore's request.** A request the settle function issues
|
|
82
|
+
* while it runs (its call reaches this client before the function awaits anything) is part of
|
|
83
|
+
* the restore it is waiting for, so it goes out immediately — `setAuthGate(() =>
|
|
84
|
+
* restoreSession())` does not deadlock even when `restoreSession` uses this client. A restore
|
|
85
|
+
* that awaits something else first and only then calls the client reaches it after that
|
|
86
|
+
* window, and that request must opt out of the gate: `http.get(currentUserEndpoint, {
|
|
87
|
+
* skipAuthGate: true })`. Without the opt-out the gate waits on itself, the restore never
|
|
88
|
+
* settles, and every request the gate holds stalls until it times out (3 s).
|
|
89
|
+
* `@molecule/app-auth`'s own restore does not need it (it calls `fetch`, not this client).
|
|
90
|
+
*
|
|
91
|
+
* **A failed request's `status` is `0` when NO response arrived — never read it as
|
|
92
|
+
* "signed out".** An aborted request (an `AbortController` signal, a component's
|
|
93
|
+
* effect cleanup, a route change tearing the fetch down) and a network outage both
|
|
94
|
+
* throw an `HttpError` with `status === 0`; the aborted ones also carry
|
|
95
|
+
* `aborted: true` and the `http.error.aborted` key, the rest `http.error.networkError`.
|
|
96
|
+
* Neither says anything about the session. To decide whether a session ended, use
|
|
97
|
+
* `isAuthFailure(err)` (401/403 only); `isNoResponse(err)` identifies the no-response
|
|
98
|
+
* case so a caller can stay silent instead of reporting an outage. **Do not write
|
|
99
|
+
* `err instanceof HttpError && err.status < 500` as a sign-out check** — it clears
|
|
100
|
+
* the session on every aborted navigation request.
|
|
88
101
|
*
|
|
89
102
|
* @module
|
|
90
103
|
*/
|
|
91
104
|
export * from './auth-gate.js';
|
|
92
105
|
export * from './client.js';
|
|
106
|
+
export * from './errors.js';
|
|
93
107
|
export * from './interceptors.js';
|
|
94
108
|
export * from './provider.js';
|
|
95
109
|
export * from './types.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsGG;AAEH,cAAc,gBAAgB,CAAA;AAC9B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA"}
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAQ/D;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAQ,gBAAqB,KAAG,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAQ/D;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAQ,gBAAqB,KAAG,UAiYjE,CAAA"}
|
package/dist/provider.js
CHANGED
|
@@ -257,9 +257,17 @@ export const createFetchClient = (config = {}) => {
|
|
|
257
257
|
else {
|
|
258
258
|
logger.error('Network error', finalConfig.method, url, err);
|
|
259
259
|
}
|
|
260
|
+
// An abort and a navigation cancellation are the SAME fact to a caller —
|
|
261
|
+
// the request was cancelled before any response — and neither is a network
|
|
262
|
+
// outage. Flag it (`aborted`) and give it its own errorKey so app code does
|
|
263
|
+
// not have to parse the message, and so a session-clearing check can tell
|
|
264
|
+
// it apart from a real failure without treating `status === 0` as a 4xx.
|
|
265
|
+
const aborted = isAbort || isNavCancel;
|
|
260
266
|
const error = new HttpError(err instanceof Error
|
|
261
267
|
? err.message
|
|
262
|
-
: t('http.error.
|
|
268
|
+
: t(aborted ? 'http.error.aborted' : 'http.error.networkError', undefined, {
|
|
269
|
+
defaultValue: aborted ? 'Request aborted' : 'Network error',
|
|
270
|
+
}), 0, undefined, finalConfig, aborted ? 'http.error.aborted' : 'http.error.networkError', aborted);
|
|
263
271
|
// Apply error interceptors
|
|
264
272
|
let finalError = error;
|
|
265
273
|
for (const interceptor of errorInterceptors) {
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -30,11 +30,15 @@ export interface RequestConfig {
|
|
|
30
30
|
/**
|
|
31
31
|
* Send this request WITHOUT waiting for the session restore (the auth gate).
|
|
32
32
|
*
|
|
33
|
-
* A request the gate
|
|
34
|
-
*
|
|
35
|
-
* client
|
|
36
|
-
*
|
|
37
|
-
*
|
|
33
|
+
* A request the gate's restore issues from a LATER continuation must set this. The gate
|
|
34
|
+
* recognizes a request the settle function issues while it runs and never holds it — this
|
|
35
|
+
* package's client awaits the gate before anything else, so a `restoreSession()` that calls
|
|
36
|
+
* it directly does not deadlock. But a restore that awaits something else first
|
|
37
|
+
* (`await storage.get()`), then calls the client, reaches `awaitAuthGate` after that window:
|
|
38
|
+
* the gate then waits on itself, and every request on the page stalls until the gate times
|
|
39
|
+
* out (3 s) — so pass `skipAuthGate: true` on that request. A provider that awaits the gate
|
|
40
|
+
* inside a scheduled interceptor (the Axios bond) also reaches it after the window, so its
|
|
41
|
+
* restore's request needs the opt-out.
|
|
38
42
|
*
|
|
39
43
|
* ```typescript
|
|
40
44
|
* // the request the gate's restore makes, through the same client the gate holds back
|
|
@@ -43,7 +47,8 @@ export interface RequestConfig {
|
|
|
43
47
|
*
|
|
44
48
|
* `@molecule/app-auth`'s own restore does not need it — it sends its request with
|
|
45
49
|
* `fetch`, not through this client. An app with its own session store that registers a
|
|
46
|
-
* gate with `setAuthGate` does
|
|
50
|
+
* gate with `setAuthGate` does not need it either when its restore calls the client
|
|
51
|
+
* directly.
|
|
47
52
|
*/
|
|
48
53
|
skipAuthGate?: boolean;
|
|
49
54
|
/**
|
|
@@ -134,12 +139,47 @@ export interface HttpResponse<T = unknown> {
|
|
|
134
139
|
}
|
|
135
140
|
/**
|
|
136
141
|
* HTTP error with response details.
|
|
142
|
+
*
|
|
143
|
+
* **`status` is an HTTP status when the server answered, and `0` when it did not.**
|
|
144
|
+
* A `0` means NO response exists: the request was aborted (an `AbortController`, a
|
|
145
|
+
* component's effect cleanup, a route change tearing the request down) or the
|
|
146
|
+
* network failed before anything came back. It is not an HTTP status at all, so it
|
|
147
|
+
* says nothing about the session — an app must never treat `status < 500` as
|
|
148
|
+
* "signed out", because every aborted request on a route change would clear the
|
|
149
|
+
* session. The correct check is {@link isAuthFailure} (`status === 401 || status === 403`);
|
|
150
|
+
* `isNoResponse` (`status === 0`) identifies this case.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* try {
|
|
155
|
+
* await http.get('/projects')
|
|
156
|
+
* } catch (err) {
|
|
157
|
+
* if (isAuthFailure(err)) clearSession() // 401/403: the server rejected the credential
|
|
158
|
+
* else if (isNoResponse(err)) return // aborted or offline — not a session decision
|
|
159
|
+
* else showError(err)
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
137
162
|
*/
|
|
138
163
|
export declare class HttpError extends Error {
|
|
139
164
|
status: number;
|
|
140
165
|
response?: HttpResponse | undefined;
|
|
141
166
|
config?: FullRequestConfig | undefined;
|
|
142
167
|
errorKey?: string | undefined;
|
|
143
|
-
|
|
168
|
+
aborted: boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Builds a failed-request error.
|
|
171
|
+
*
|
|
172
|
+
* @param message - Human-readable message (already translated where a key exists).
|
|
173
|
+
* @param status - HTTP status, or `0` when no response was received (aborted / network failure).
|
|
174
|
+
* @param response - Parsed response when the server answered, otherwise undefined.
|
|
175
|
+
* @param config - The request config that failed.
|
|
176
|
+
* @param errorKey - Translation key for the failure (`http.error.aborted` for an
|
|
177
|
+
* aborted request, `http.error.networkError` for a real network failure).
|
|
178
|
+
* @param aborted - Whether the request was aborted before a response: an
|
|
179
|
+
* `AbortController` signal (component cleanup, a cancelled request) or the
|
|
180
|
+
* browser tearing the fetch down during a navigation. Distinguishes an abort
|
|
181
|
+
* from a network outage on the same `status === 0`, without parsing the message.
|
|
182
|
+
*/
|
|
183
|
+
constructor(message: string, status: number, response?: HttpResponse | undefined, config?: FullRequestConfig | undefined, errorKey?: string | undefined, aborted?: boolean);
|
|
144
184
|
}
|
|
145
185
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAA;AAEzF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;IAE9D;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAA;AAEzF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;IAE9D;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAA;IAEvD;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD;;OAEG;IACH,MAAM,EAAE,UAAU,CAAA;IAElB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAA;IAEX;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC;;OAEG;IACH,IAAI,EAAE,CAAC,CAAA;IAEP;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE/B;;OAEG;IACH,MAAM,EAAE,iBAAiB,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAiBzB,MAAM,EAAE,MAAM;IACd,QAAQ,CAAC,EAAE,YAAY;IACvB,MAAM,CAAC,EAAE,iBAAiB;IAC1B,QAAQ,CAAC,EAAE,MAAM;IACjB,OAAO;IApBhB;;;;;;;;;;;;;OAaG;gBAED,OAAO,EAAE,MAAM,EACR,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,YAAY,YAAA,EACvB,MAAM,CAAC,EAAE,iBAAiB,YAAA,EAC1B,QAAQ,CAAC,EAAE,MAAM,YAAA,EACjB,OAAO,UAAQ;CAKzB"}
|
package/dist/types.js
CHANGED
|
@@ -5,18 +5,54 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/**
|
|
7
7
|
* HTTP error with response details.
|
|
8
|
+
*
|
|
9
|
+
* **`status` is an HTTP status when the server answered, and `0` when it did not.**
|
|
10
|
+
* A `0` means NO response exists: the request was aborted (an `AbortController`, a
|
|
11
|
+
* component's effect cleanup, a route change tearing the request down) or the
|
|
12
|
+
* network failed before anything came back. It is not an HTTP status at all, so it
|
|
13
|
+
* says nothing about the session — an app must never treat `status < 500` as
|
|
14
|
+
* "signed out", because every aborted request on a route change would clear the
|
|
15
|
+
* session. The correct check is {@link isAuthFailure} (`status === 401 || status === 403`);
|
|
16
|
+
* `isNoResponse` (`status === 0`) identifies this case.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* try {
|
|
21
|
+
* await http.get('/projects')
|
|
22
|
+
* } catch (err) {
|
|
23
|
+
* if (isAuthFailure(err)) clearSession() // 401/403: the server rejected the credential
|
|
24
|
+
* else if (isNoResponse(err)) return // aborted or offline — not a session decision
|
|
25
|
+
* else showError(err)
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
8
28
|
*/
|
|
9
29
|
export class HttpError extends Error {
|
|
10
30
|
status;
|
|
11
31
|
response;
|
|
12
32
|
config;
|
|
13
33
|
errorKey;
|
|
14
|
-
|
|
34
|
+
aborted;
|
|
35
|
+
/**
|
|
36
|
+
* Builds a failed-request error.
|
|
37
|
+
*
|
|
38
|
+
* @param message - Human-readable message (already translated where a key exists).
|
|
39
|
+
* @param status - HTTP status, or `0` when no response was received (aborted / network failure).
|
|
40
|
+
* @param response - Parsed response when the server answered, otherwise undefined.
|
|
41
|
+
* @param config - The request config that failed.
|
|
42
|
+
* @param errorKey - Translation key for the failure (`http.error.aborted` for an
|
|
43
|
+
* aborted request, `http.error.networkError` for a real network failure).
|
|
44
|
+
* @param aborted - Whether the request was aborted before a response: an
|
|
45
|
+
* `AbortController` signal (component cleanup, a cancelled request) or the
|
|
46
|
+
* browser tearing the fetch down during a navigation. Distinguishes an abort
|
|
47
|
+
* from a network outage on the same `status === 0`, without parsing the message.
|
|
48
|
+
*/
|
|
49
|
+
constructor(message, status, response, config, errorKey, aborted = false) {
|
|
15
50
|
super(message);
|
|
16
51
|
this.status = status;
|
|
17
52
|
this.response = response;
|
|
18
53
|
this.config = config;
|
|
19
54
|
this.errorKey = errorKey;
|
|
55
|
+
this.aborted = aborted;
|
|
20
56
|
this.name = 'HttpError';
|
|
21
57
|
}
|
|
22
58
|
}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA6JH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAiBzB;IACA;IACA;IACA;IACA;IApBT;;;;;;;;;;;;;OAaG;IACH,YACE,OAAe,EACR,MAAc,EACd,QAAuB,EACvB,MAA0B,EAC1B,QAAiB,EACjB,UAAU,KAAK;QAEtB,KAAK,CAAC,OAAO,CAAC,CAAA;QANP,WAAM,GAAN,MAAM,CAAQ;QACd,aAAQ,GAAR,QAAQ,CAAe;QACvB,WAAM,GAAN,MAAM,CAAoB;QAC1B,aAAQ,GAAR,QAAQ,CAAS;QACjB,YAAO,GAAP,OAAO,CAAQ;QAGtB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;IACzB,CAAC;CACF"}
|