@molecule/app-http 1.1.2 → 1.1.4
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 +125 -27
- package/dist/auth-gate.d.ts +31 -2
- package/dist/auth-gate.d.ts.map +1 -1
- package/dist/auth-gate.js +98 -9
- package/dist/auth-gate.js.map +1 -1
- package/dist/client.d.ts +13 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/index.d.ts +28 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -3
- package/dist/index.js.map +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +3 -1
- package/dist/provider.js.map +1 -1
- package/dist/types.d.ts +48 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities.d.ts +14 -6
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +14 -6
- package/dist/utilities.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,20 +3,30 @@ 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-17T07:08:43.988Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/app-http
|
|
10
10
|
|
|
11
|
-
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
-
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
-
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
-
|
|
15
11
|
Client HTTP interface for molecule.dev.
|
|
16
12
|
|
|
17
13
|
Provides a unified HTTP client API that works across different
|
|
18
14
|
HTTP libraries (fetch, axios, ky, etc.).
|
|
19
15
|
|
|
16
|
+
**The body is the SECOND argument: `post(url, data, config?)` — likewise `put` and `patch`,
|
|
17
|
+
and the response is `HttpResponse<T>` (read `.data` for the body).** `data` IS the request
|
|
18
|
+
body; a plain object is serialized as the JSON body. Passing `{ data: body }` there is NOT a
|
|
19
|
+
config object — it makes the wire body `{"data":{…}}`, so the API sees an object whose only
|
|
20
|
+
key is `data`, finds none of the fields it validates, and answers
|
|
21
|
+
`422 {"errors":{"username":["can't be blank"],…}}`. Write `post('/users', { user })`, never
|
|
22
|
+
`post('/users', { data: { user } })`. The config object (headers, params, timeout,
|
|
23
|
+
`skipAuthGate`) is the THIRD argument. Only `request({ method, url, data, … })` takes `data`
|
|
24
|
+
inside an options object, because there that object IS the config.
|
|
25
|
+
|
|
26
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
27
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
28
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
29
|
+
|
|
20
30
|
## Quick Start
|
|
21
31
|
|
|
22
32
|
```tsx
|
|
@@ -31,7 +41,10 @@ function Plants() {
|
|
|
31
41
|
const res = await http.get<Plant[]>('/plants') // baseURL ('/api') is prepended
|
|
32
42
|
setPlants(res.data)
|
|
33
43
|
}
|
|
34
|
-
//
|
|
44
|
+
// Body-carrying verbs take the body as the SECOND argument:
|
|
45
|
+
// http.post('/plants', plant) — wire body is `plant`
|
|
46
|
+
// http.post('/plants', { data: plant }) — WRONG: wire body is `{"data": plant}`
|
|
47
|
+
// http.put(url, body), http.patch(url, body) and http.delete(url) are also available.
|
|
35
48
|
}
|
|
36
49
|
```
|
|
37
50
|
|
|
@@ -68,7 +81,8 @@ interface HttpClient {
|
|
|
68
81
|
defaultHeaders: Record<string, string>
|
|
69
82
|
|
|
70
83
|
/**
|
|
71
|
-
* Makes a generic HTTP request.
|
|
84
|
+
* Makes a generic HTTP request. `data` is a field of THIS config object — the same body
|
|
85
|
+
* `post(url, data, config)` takes as its second argument.
|
|
72
86
|
*/
|
|
73
87
|
request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
|
|
74
88
|
|
|
@@ -78,17 +92,21 @@ interface HttpClient {
|
|
|
78
92
|
get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
79
93
|
|
|
80
94
|
/**
|
|
81
|
-
* Makes a POST request.
|
|
95
|
+
* Makes a POST request. `data` is the request BODY, not a config object: the wire body is
|
|
96
|
+
* `data` itself, so `post(url, { data: body })` sends `{"data":body}` — pass `body` directly.
|
|
97
|
+
* A config (headers, params) is the THIRD argument.
|
|
82
98
|
*/
|
|
83
99
|
post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
84
100
|
|
|
85
101
|
/**
|
|
86
|
-
* Makes a PUT request.
|
|
102
|
+
* Makes a PUT request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
103
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
87
104
|
*/
|
|
88
105
|
put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
89
106
|
|
|
90
107
|
/**
|
|
91
|
-
* Makes a PATCH request.
|
|
108
|
+
* Makes a PATCH request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
109
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
92
110
|
*/
|
|
93
111
|
patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
94
112
|
|
|
@@ -163,7 +181,10 @@ interface HttpClientConfig {
|
|
|
163
181
|
/**
|
|
164
182
|
* The scheme of the `Authorization` header the auth token is sent with:
|
|
165
183
|
* `Bearer` (default), or what your API expects, e.g. `Token` for an API that
|
|
166
|
-
* reads `Authorization: Token <jwt>`.
|
|
184
|
+
* reads `Authorization: Token <jwt>`. It is an option of the client's
|
|
185
|
+
* CONSTRUCTOR (`createFetchClient({ baseURL, authScheme: 'Token' })`, or the
|
|
186
|
+
* bonded provider's `createAxiosClient({ … })`), never a property of the client
|
|
187
|
+
* it returns.
|
|
167
188
|
*/
|
|
168
189
|
authScheme?: string
|
|
169
190
|
}
|
|
@@ -173,7 +194,7 @@ interface HttpClientConfig {
|
|
|
173
194
|
|
|
174
195
|
HTTP request options (headers, query params, timeout, credentials, response type, abort signal).
|
|
175
196
|
|
|
176
|
-
|
|
197
|
+
````typescript
|
|
177
198
|
interface RequestConfig {
|
|
178
199
|
/**
|
|
179
200
|
* Request headers.
|
|
@@ -195,6 +216,26 @@ interface RequestConfig {
|
|
|
195
216
|
*/
|
|
196
217
|
withCredentials?: boolean
|
|
197
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Send this request WITHOUT waiting for the session restore (the auth gate).
|
|
221
|
+
*
|
|
222
|
+
* A request the gate itself depends on must set this. A gate registered with
|
|
223
|
+
* `setAuthGate` that waits for a session restore whose own request goes through this
|
|
224
|
+
* client otherwise waits on itself: the gate holds the restore's request, the restore's
|
|
225
|
+
* promise never settles, and every request on the page stalls until the gate times out —
|
|
226
|
+
* so pass `skipAuthGate: true` on the restore's own request:
|
|
227
|
+
*
|
|
228
|
+
* ```typescript
|
|
229
|
+
* // the request the gate's restore makes, through the same client the gate holds back
|
|
230
|
+
* await http.get(currentUserEndpoint, { skipAuthGate: true })
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* `@molecule/app-auth`'s own restore does not need it — it sends its request with
|
|
234
|
+
* `fetch`, not through this client. An app with its own session store that registers a
|
|
235
|
+
* gate with `setAuthGate` does.
|
|
236
|
+
*/
|
|
237
|
+
skipAuthGate?: boolean
|
|
238
|
+
|
|
198
239
|
/**
|
|
199
240
|
* Response type.
|
|
200
241
|
*/
|
|
@@ -206,7 +247,11 @@ interface RequestConfig {
|
|
|
206
247
|
signal?: AbortSignal
|
|
207
248
|
|
|
208
249
|
/**
|
|
209
|
-
* Request body data
|
|
250
|
+
* Request body data, as a field of THIS config object — the `request({ method, url, data })`
|
|
251
|
+
* form. The verb methods take the body as their SECOND argument: `post(url, data, config)`,
|
|
252
|
+
* `put(url, data, config)`, `patch(url, data, config)`. Never wrap it there as
|
|
253
|
+
* `{ data: body }`: that object is the body, so the wire sends `{"data":body}` and the API
|
|
254
|
+
* sees none of the fields at its top level.
|
|
210
255
|
*/
|
|
211
256
|
data?: unknown
|
|
212
257
|
|
|
@@ -215,6 +260,35 @@ interface RequestConfig {
|
|
|
215
260
|
*/
|
|
216
261
|
options?: Record<string, unknown>
|
|
217
262
|
}
|
|
263
|
+
````
|
|
264
|
+
|
|
265
|
+
#### `AuthGateRequest`
|
|
266
|
+
|
|
267
|
+
What the auth gate is told about the request it is about to hold: whether the request
|
|
268
|
+
opts out of the wait, and how to name it in the stalled-gate report.
|
|
269
|
+
|
|
270
|
+
A request's own `RequestConfig` satisfies this — the providers pass it straight through
|
|
271
|
+
(`awaitAuthGate(requestConfig)`), so a provider never has to build one by hand.
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
interface AuthGateRequest {
|
|
275
|
+
/**
|
|
276
|
+
* Send this request without waiting for the gate at all — see
|
|
277
|
+
* `RequestConfig.skipAuthGate`.
|
|
278
|
+
*/
|
|
279
|
+
skipAuthGate?: boolean
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* The request's HTTP method, for the message logged when the gate never settles.
|
|
283
|
+
*/
|
|
284
|
+
method?: string
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* The request's URL, for the message logged when the gate never settles. A URL may carry
|
|
288
|
+
* an id; it never carries a credential (tokens travel in headers).
|
|
289
|
+
*/
|
|
290
|
+
url?: string
|
|
291
|
+
}
|
|
218
292
|
```
|
|
219
293
|
|
|
220
294
|
#### `FullRequestConfig`
|
|
@@ -234,7 +308,7 @@ interface FullRequestConfig extends RequestConfig {
|
|
|
234
308
|
url: string
|
|
235
309
|
|
|
236
310
|
/**
|
|
237
|
-
* Request body data.
|
|
311
|
+
* Request body data — a field of this config object, never a second argument here.
|
|
238
312
|
*/
|
|
239
313
|
data?: unknown
|
|
240
314
|
}
|
|
@@ -349,13 +423,18 @@ template auth that is `() => authClient.whenRestored()`, which resolves
|
|
|
349
423
|
immediately when no restore is in flight, so registering it never makes a
|
|
350
424
|
request wait longer than the restore it was about to race anyway.
|
|
351
425
|
|
|
426
|
+
A gate whose restore sends its OWN request through the gated client deadlocks — the
|
|
427
|
+
gate holds the request it is waiting for. That request must pass `skipAuthGate: true`
|
|
428
|
+
(see `RequestConfig.skipAuthGate`); `@molecule/app-auth`'s own restore does not
|
|
429
|
+
need it because it uses `fetch` rather than the bonded client.
|
|
430
|
+
|
|
352
431
|
```typescript
|
|
353
432
|
function setAuthGate(next: (() => Promise<void>) | null): void
|
|
354
433
|
```
|
|
355
434
|
|
|
356
435
|
- `next` — The gate, or `null` to clear a previously registered one.
|
|
357
436
|
|
|
358
|
-
#### `awaitAuthGate()`
|
|
437
|
+
#### `awaitAuthGate(request)`
|
|
359
438
|
|
|
360
439
|
Awaits the registered gate, if any. Every HTTP provider calls this before it
|
|
361
440
|
sends a request; callers never need to.
|
|
@@ -363,12 +442,15 @@ sends a request; callers never need to.
|
|
|
363
442
|
A gate that rejects (a restore that failed) is logged and cleared of consequence: the request
|
|
364
443
|
is sent rather than held forever, because a dead restore must not block every request for the
|
|
365
444
|
life of the page. The same holds for a gate that never settles — the wait is bounded by
|
|
366
|
-
|
|
445
|
+
`GATE_TIMEOUT_MS`, and a timeout with requests held is reported at error level naming the fix
|
|
446
|
+
(`skipAuthGate`).
|
|
367
447
|
|
|
368
448
|
```typescript
|
|
369
|
-
function awaitAuthGate(): Promise<void>
|
|
449
|
+
function awaitAuthGate(request?: AuthGateRequest): Promise<void>
|
|
370
450
|
```
|
|
371
451
|
|
|
452
|
+
- `request` — The request being gated, so a request the gate itself depends on can opt out (`skipAuthGate`) and a stalled gate can name what it held. A provider passes its own request config; a caller passing nothing gets the plain wait.
|
|
453
|
+
|
|
372
454
|
**Returns:** A promise that settles when the gate has released the request.
|
|
373
455
|
|
|
374
456
|
#### `createFetchClient(config)`
|
|
@@ -481,13 +563,17 @@ function get(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
|
481
563
|
|
|
482
564
|
Makes a POST request using the bonded HTTP client.
|
|
483
565
|
|
|
566
|
+
The body is `data` — the SECOND argument. `post(url, { data: body })` sends the JSON body
|
|
567
|
+
`{"data":body}`, not `body`, so the API finds none of its fields at the top level; pass the
|
|
568
|
+
body directly (`post('/users', { user })`). The config is the THIRD argument.
|
|
569
|
+
|
|
484
570
|
```typescript
|
|
485
571
|
function post(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
486
572
|
```
|
|
487
573
|
|
|
488
574
|
- `url` — The request URL.
|
|
489
|
-
- `data` — The request body.
|
|
490
|
-
- `config` — Optional request configuration.
|
|
575
|
+
- `data` — The request body itself (never `{ data: body }`).
|
|
576
|
+
- `config` — Optional request configuration (headers, params, timeout).
|
|
491
577
|
|
|
492
578
|
**Returns:** The HTTP response with typed data.
|
|
493
579
|
|
|
@@ -499,9 +585,9 @@ Makes a PUT request using the bonded HTTP client.
|
|
|
499
585
|
function put(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
500
586
|
```
|
|
501
587
|
|
|
502
|
-
- `url` — The request URL.
|
|
503
|
-
- `data` — The request body.
|
|
504
|
-
- `config` — Optional request configuration.
|
|
588
|
+
- `url` — The request URL. The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
589
|
+
- `data` — The request body itself.
|
|
590
|
+
- `config` — Optional request configuration (the third argument).
|
|
505
591
|
|
|
506
592
|
**Returns:** The HTTP response with typed data.
|
|
507
593
|
|
|
@@ -513,9 +599,9 @@ Makes a PATCH request using the bonded HTTP client.
|
|
|
513
599
|
function patch(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
514
600
|
```
|
|
515
601
|
|
|
516
|
-
- `url` — The request URL.
|
|
517
|
-
- `data` — The request body (partial update).
|
|
518
|
-
- `config` — Optional request configuration.
|
|
602
|
+
- `url` — The request URL. The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
603
|
+
- `data` — The request body itself (the partial update).
|
|
604
|
+
- `config` — Optional request configuration (the third argument).
|
|
519
605
|
|
|
520
606
|
**Returns:** The HTTP response with typed data.
|
|
521
607
|
|
|
@@ -586,8 +672,12 @@ Two mistakes that break in preview/production (seen in real imported apps):
|
|
|
586
672
|
Auth (the bearer token / session cookie) is attached by the client's interceptors — do not
|
|
587
673
|
read a token from `localStorage` or hand-attach it (the token is memory-only; see the user
|
|
588
674
|
resource).
|
|
589
|
-
An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`)
|
|
590
|
-
`authScheme: 'Token'`
|
|
675
|
+
An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`) passes
|
|
676
|
+
`authScheme: 'Token'` to the client's CONSTRUCTOR — `setClient(createFetchClient({ baseURL,
|
|
677
|
+
authScheme: 'Token' }))`, or the bonded provider's constructor
|
|
678
|
+
(`createAxiosClient({ … })` from `@molecule/app-http-axios`). It is NOT a property of
|
|
679
|
+
`getClient()`'s result: that is a built client, and `client.authScheme = 'Token'` is a type
|
|
680
|
+
error (TS2339) that changes no header. Do not hand-write a fetch wrapper for the scheme either.
|
|
591
681
|
|
|
592
682
|
A request made while the session is still being restored WAITS for that restore, so a page
|
|
593
683
|
that fetches viewer-dependent data on mount (a profile's `following` flag, a feed, a
|
|
@@ -596,6 +686,14 @@ bond registers that wait with `setAuthGate`; apps that bond auth through
|
|
|
596
686
|
`@molecule/app-bonds-default-react` get it without doing anything. An app with its own session
|
|
597
687
|
module registers its own: `setAuthGate(() => session.whenRestored())`.
|
|
598
688
|
|
|
689
|
+
**A request the gate itself depends on must opt out of it: pass `skipAuthGate: true`.** A gate
|
|
690
|
+
that waits for a session restore whose own request goes through this client waits on itself —
|
|
691
|
+
that request is held by the gate waiting for it, so the restore never settles and every request
|
|
692
|
+
the gate holds stalls until it times out (3 s). The request that restores the session for a gate
|
|
693
|
+
you registered yourself is therefore written
|
|
694
|
+
`http.get(currentUserEndpoint, { skipAuthGate: true })`; `@molecule/app-auth`'s own restore does
|
|
695
|
+
not need it (it calls `fetch`, not this client).
|
|
696
|
+
|
|
599
697
|
## Translations
|
|
600
698
|
|
|
601
699
|
Translation strings are provided by `@molecule/app-locales-http`.
|
package/dist/auth-gate.d.ts
CHANGED
|
@@ -20,8 +20,28 @@
|
|
|
20
20
|
* `setupHttpDefault()`), and a gate installed on the throwaway client the auth
|
|
21
21
|
* bond saw would be silently lost.
|
|
22
22
|
*
|
|
23
|
+
* ## A request the gate is waiting for must opt out
|
|
24
|
+
*
|
|
25
|
+
* `awaitAuthGate` holds every request while the gate is pending — including one the gate
|
|
26
|
+
* itself depends on. A gate that waits for a session restore whose own request goes through
|
|
27
|
+
* the SAME client waits on itself: the restore's `GET /users/me` is held by the gate, the
|
|
28
|
+
* restore's promise cannot settle, and nothing but the timeout releases anything (X1
|
|
29
|
+
* xr-molecule-flash-m97 lost ~4 min to exactly this — an app registering
|
|
30
|
+
* `setAuthGate(() => whenSettled())` over a restore that fetched through its own client, with
|
|
31
|
+
* every request stalling the full bound and only a console warning to show for it). So a
|
|
32
|
+
* request the gate's restore makes must pass `skipAuthGate: true`
|
|
33
|
+
* (`RequestConfig.skipAuthGate`).
|
|
34
|
+
*
|
|
35
|
+
* Which held request is the gate's own is NOT detectable here: the gate is arbitrary code
|
|
36
|
+
* returning a promise, so a request cannot be attributed to the async chain that awaits it —
|
|
37
|
+
* and browsers have no async-context API (`AsyncContext` is not shipped) to ask. Releasing
|
|
38
|
+
* requests merely because the gate is pending and they carry no token would drop exactly the
|
|
39
|
+
* first-paint requests the gate exists to hold. The opt-out is therefore the fix, and a
|
|
40
|
+
* timeout with requests held is reported as an error naming it.
|
|
41
|
+
*
|
|
23
42
|
* @module
|
|
24
43
|
*/
|
|
44
|
+
import type { AuthGateRequest } from './types.js';
|
|
25
45
|
/**
|
|
26
46
|
* Registers the gate every HTTP request awaits before it is sent, or clears it
|
|
27
47
|
* with `null`.
|
|
@@ -31,6 +51,11 @@
|
|
|
31
51
|
* immediately when no restore is in flight, so registering it never makes a
|
|
32
52
|
* request wait longer than the restore it was about to race anyway.
|
|
33
53
|
*
|
|
54
|
+
* A gate whose restore sends its OWN request through the gated client deadlocks — the
|
|
55
|
+
* gate holds the request it is waiting for. That request must pass `skipAuthGate: true`
|
|
56
|
+
* (see `RequestConfig.skipAuthGate`); `@molecule/app-auth`'s own restore does not
|
|
57
|
+
* need it because it uses `fetch` rather than the bonded client.
|
|
58
|
+
*
|
|
34
59
|
* @param next - The gate, or `null` to clear a previously registered one.
|
|
35
60
|
*
|
|
36
61
|
* @example
|
|
@@ -48,9 +73,13 @@ export declare const setAuthGate: (next: (() => Promise<void>) | null) => void;
|
|
|
48
73
|
* A gate that rejects (a restore that failed) is logged and cleared of consequence: the request
|
|
49
74
|
* is sent rather than held forever, because a dead restore must not block every request for the
|
|
50
75
|
* life of the page. The same holds for a gate that never settles — the wait is bounded by
|
|
51
|
-
*
|
|
76
|
+
* `GATE_TIMEOUT_MS`, and a timeout with requests held is reported at error level naming the fix
|
|
77
|
+
* (`skipAuthGate`).
|
|
52
78
|
*
|
|
79
|
+
* @param request - The request being gated, so a request the gate itself depends on can opt
|
|
80
|
+
* out (`skipAuthGate`) and a stalled gate can name what it held. A provider passes its own
|
|
81
|
+
* request config; a caller passing nothing gets the plain wait.
|
|
53
82
|
* @returns A promise that settles when the gate has released the request.
|
|
54
83
|
*/
|
|
55
|
-
export declare const awaitAuthGate: () => Promise<void>;
|
|
84
|
+
export declare const awaitAuthGate: (request?: AuthGateRequest) => Promise<void>;
|
|
56
85
|
//# sourceMappingURL=auth-gate.d.ts.map
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AA6CjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAG,IAGhE,CAAA;AA6BD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,GAAU,UAAU,eAAe,KAAG,OAAO,CAAC,IAAI,CAuC3E,CAAA"}
|
package/dist/auth-gate.js
CHANGED
|
@@ -20,22 +20,66 @@
|
|
|
20
20
|
* `setupHttpDefault()`), and a gate installed on the throwaway client the auth
|
|
21
21
|
* bond saw would be silently lost.
|
|
22
22
|
*
|
|
23
|
+
* ## A request the gate is waiting for must opt out
|
|
24
|
+
*
|
|
25
|
+
* `awaitAuthGate` holds every request while the gate is pending — including one the gate
|
|
26
|
+
* itself depends on. A gate that waits for a session restore whose own request goes through
|
|
27
|
+
* the SAME client waits on itself: the restore's `GET /users/me` is held by the gate, the
|
|
28
|
+
* restore's promise cannot settle, and nothing but the timeout releases anything (X1
|
|
29
|
+
* xr-molecule-flash-m97 lost ~4 min to exactly this — an app registering
|
|
30
|
+
* `setAuthGate(() => whenSettled())` over a restore that fetched through its own client, with
|
|
31
|
+
* every request stalling the full bound and only a console warning to show for it). So a
|
|
32
|
+
* request the gate's restore makes must pass `skipAuthGate: true`
|
|
33
|
+
* (`RequestConfig.skipAuthGate`).
|
|
34
|
+
*
|
|
35
|
+
* Which held request is the gate's own is NOT detectable here: the gate is arbitrary code
|
|
36
|
+
* returning a promise, so a request cannot be attributed to the async chain that awaits it —
|
|
37
|
+
* and browsers have no async-context API (`AsyncContext` is not shipped) to ask. Releasing
|
|
38
|
+
* requests merely because the gate is pending and they carry no token would drop exactly the
|
|
39
|
+
* first-paint requests the gate exists to hold. The opt-out is therefore the fix, and a
|
|
40
|
+
* timeout with requests held is reported as an error naming it.
|
|
41
|
+
*
|
|
23
42
|
* @module
|
|
24
43
|
*/
|
|
25
44
|
import { getLogger } from '@molecule/app-logger';
|
|
26
45
|
const logger = getLogger('http');
|
|
27
46
|
/** The registered gate, or null when no auth bond wired one (anonymous apps). */
|
|
28
47
|
let gate = null;
|
|
48
|
+
/**
|
|
49
|
+
* The requests the gate is holding right now, keyed by the waiting request: `GET /users/me`.
|
|
50
|
+
* Read only by the stalled-gate report, so it can name what was held back.
|
|
51
|
+
*/
|
|
52
|
+
const heldRequests = new Map();
|
|
53
|
+
/**
|
|
54
|
+
* The gate whose wait timed out with requests held, reported once.
|
|
55
|
+
*
|
|
56
|
+
* A deadlocked gate times out for EVERY request it holds, and the caller's own page shows it
|
|
57
|
+
* as one fault: one report per stuck gate names the fix, N reports (one per request, on every
|
|
58
|
+
* page load) are noise — and console errors are read by users and by strict console-error
|
|
59
|
+
* gates. Cleared when the same gate later releases a request normally.
|
|
60
|
+
*/
|
|
61
|
+
let reportedStall = null;
|
|
29
62
|
/**
|
|
30
63
|
* How long a request may be held by the gate before it is sent anyway.
|
|
31
64
|
*
|
|
32
65
|
* The gate waits for the session restore, and a restore that never settles — a stalled
|
|
33
66
|
* connection, an endpoint that hangs without answering — must not hold back every request for
|
|
34
67
|
* the life of the page: an unauthenticated request that arrives is a better failure than an app
|
|
35
|
-
* that never loads. A settled restore is what the deployed race needs (one round trip,
|
|
36
|
-
* of milliseconds), so this bound is far above any wait it is meant to cause.
|
|
68
|
+
* that never loads. A settled restore is what the deployed race needs (one round trip,
|
|
69
|
+
* hundreds of milliseconds), so this bound is far above any wait it is meant to cause.
|
|
70
|
+
*
|
|
71
|
+
* It is also the cost of a gate that was wired wrong (its restore sends its request through
|
|
72
|
+
* the client the gate holds back — see the module doc): every request it holds stalls this
|
|
73
|
+
* long before it goes out. Measured, so the bound is a number and not a guess:
|
|
74
|
+
* `createJWTAuthClient.initialize()` against a server answering `/users/me` after a delay
|
|
75
|
+
* costs exactly one round trip (0 ms → 7-50 ms; 140 ms → 152-194 ms; 400 ms → 402-413 ms),
|
|
76
|
+
* and a real deployed round trip measures ~140 ms from this VM to a Fly `iad` machine
|
|
77
|
+
* (`docs/experiments/x0/live/task-deployed-latency.report.md`) with 300-410 ms to a deployed
|
|
78
|
+
* app's proxied path over the open internet. 3 s is therefore ~8-20x a normal restore and
|
|
79
|
+
* still clears a slow mobile link — while a missed opt-out costs at most 3 s per request
|
|
80
|
+
* instead of 10.
|
|
37
81
|
*/
|
|
38
|
-
const GATE_TIMEOUT_MS =
|
|
82
|
+
const GATE_TIMEOUT_MS = 3_000;
|
|
39
83
|
/**
|
|
40
84
|
* Registers the gate every HTTP request awaits before it is sent, or clears it
|
|
41
85
|
* with `null`.
|
|
@@ -45,6 +89,11 @@ const GATE_TIMEOUT_MS = 10_000;
|
|
|
45
89
|
* immediately when no restore is in flight, so registering it never makes a
|
|
46
90
|
* request wait longer than the restore it was about to race anyway.
|
|
47
91
|
*
|
|
92
|
+
* A gate whose restore sends its OWN request through the gated client deadlocks — the
|
|
93
|
+
* gate holds the request it is waiting for. That request must pass `skipAuthGate: true`
|
|
94
|
+
* (see `RequestConfig.skipAuthGate`); `@molecule/app-auth`'s own restore does not
|
|
95
|
+
* need it because it uses `fetch` rather than the bonded client.
|
|
96
|
+
*
|
|
48
97
|
* @param next - The gate, or `null` to clear a previously registered one.
|
|
49
98
|
*
|
|
50
99
|
* @example
|
|
@@ -56,6 +105,30 @@ const GATE_TIMEOUT_MS = 10_000;
|
|
|
56
105
|
*/
|
|
57
106
|
export const setAuthGate = (next) => {
|
|
58
107
|
gate = next;
|
|
108
|
+
reportedStall = null;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Names a held request for the stalled-gate report. A provider that passes no request
|
|
112
|
+
* description still gets a report — it just cannot say which request was held.
|
|
113
|
+
*/
|
|
114
|
+
const describeRequest = (request) => request?.method || request?.url
|
|
115
|
+
? `${request?.method ?? 'GET'} ${request?.url ?? ''}`.trim()
|
|
116
|
+
: 'a request';
|
|
117
|
+
/**
|
|
118
|
+
* Reports a gate that timed out while holding requests: once per stuck gate, at error level
|
|
119
|
+
* so it reaches the page's error console and any error transport — a console warning on a
|
|
120
|
+
* deployed URL reads as "the site is slow", which is what the gate itself was added for.
|
|
121
|
+
*/
|
|
122
|
+
const reportStalledGate = (stuck) => {
|
|
123
|
+
if (reportedStall === stuck)
|
|
124
|
+
return;
|
|
125
|
+
reportedStall = stuck;
|
|
126
|
+
const held = [...heldRequests.values()].join(', ');
|
|
127
|
+
logger.error(`The auth gate has not settled after ${GATE_TIMEOUT_MS}ms and ${heldRequests.size} request(s) ` +
|
|
128
|
+
`were held by it (${held}); sending them without waiting. If the gate waits for a session ` +
|
|
129
|
+
`restore that makes its own request through this HTTP client, that request is being held by ` +
|
|
130
|
+
`the gate waiting for it: send it with \`skipAuthGate: true\`, or clear the gate with ` +
|
|
131
|
+
`\`setAuthGate(null)\` if nothing restores a session.`);
|
|
59
132
|
};
|
|
60
133
|
/**
|
|
61
134
|
* Awaits the registered gate, if any. Every HTTP provider calls this before it
|
|
@@ -64,19 +137,31 @@ export const setAuthGate = (next) => {
|
|
|
64
137
|
* A gate that rejects (a restore that failed) is logged and cleared of consequence: the request
|
|
65
138
|
* is sent rather than held forever, because a dead restore must not block every request for the
|
|
66
139
|
* life of the page. The same holds for a gate that never settles — the wait is bounded by
|
|
67
|
-
*
|
|
140
|
+
* `GATE_TIMEOUT_MS`, and a timeout with requests held is reported at error level naming the fix
|
|
141
|
+
* (`skipAuthGate`).
|
|
68
142
|
*
|
|
143
|
+
* @param request - The request being gated, so a request the gate itself depends on can opt
|
|
144
|
+
* out (`skipAuthGate`) and a stalled gate can name what it held. A provider passes its own
|
|
145
|
+
* request config; a caller passing nothing gets the plain wait.
|
|
69
146
|
* @returns A promise that settles when the gate has released the request.
|
|
70
147
|
*/
|
|
71
|
-
export const awaitAuthGate = async () => {
|
|
148
|
+
export const awaitAuthGate = async (request) => {
|
|
149
|
+
// The request IS the gate's restore (or otherwise must not wait): holding it would make
|
|
150
|
+
// the gate wait on itself — see the module doc.
|
|
151
|
+
if (request?.skipAuthGate)
|
|
152
|
+
return;
|
|
72
153
|
const current = gate;
|
|
73
154
|
if (!current)
|
|
74
155
|
return;
|
|
156
|
+
const token = Symbol('held-request');
|
|
157
|
+
heldRequests.set(token, describeRequest(request));
|
|
75
158
|
let timer;
|
|
76
159
|
let timedOut = false;
|
|
77
160
|
try {
|
|
78
161
|
await Promise.race([
|
|
79
|
-
|
|
162
|
+
// `(async () => current())()` also turns a gate that throws SYNCHRONOUSLY into a rejection:
|
|
163
|
+
// a gate is someone else's code, and no shape of it may reject the request it was holding.
|
|
164
|
+
(async () => current())().catch((error) => {
|
|
80
165
|
logger.warn('The auth gate rejected; sending the request without waiting for it', {
|
|
81
166
|
error,
|
|
82
167
|
});
|
|
@@ -84,6 +169,8 @@ export const awaitAuthGate = async () => {
|
|
|
84
169
|
new Promise((resolve) => {
|
|
85
170
|
timer = setTimeout(() => {
|
|
86
171
|
timedOut = true;
|
|
172
|
+
// Reported while this request is still in `heldRequests`, so the message names it.
|
|
173
|
+
reportStalledGate(current);
|
|
87
174
|
resolve();
|
|
88
175
|
}, GATE_TIMEOUT_MS);
|
|
89
176
|
}),
|
|
@@ -92,9 +179,11 @@ export const awaitAuthGate = async () => {
|
|
|
92
179
|
finally {
|
|
93
180
|
if (timer)
|
|
94
181
|
clearTimeout(timer);
|
|
182
|
+
heldRequests.delete(token);
|
|
95
183
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
184
|
+
// The gate released a real request, so any stall reported for it is over: a later one is
|
|
185
|
+
// news again (a fresh restore on a gate that was merely slow the first time).
|
|
186
|
+
if (!timedOut && reportedStall === current)
|
|
187
|
+
reportedStall = null;
|
|
99
188
|
};
|
|
100
189
|
//# sourceMappingURL=auth-gate.js.map
|
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/client.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export interface HttpClient {
|
|
|
22
22
|
*/
|
|
23
23
|
defaultHeaders: Record<string, string>;
|
|
24
24
|
/**
|
|
25
|
-
* Makes a generic HTTP request.
|
|
25
|
+
* Makes a generic HTTP request. `data` is a field of THIS config object — the same body
|
|
26
|
+
* `post(url, data, config)` takes as its second argument.
|
|
26
27
|
*/
|
|
27
28
|
request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>;
|
|
28
29
|
/**
|
|
@@ -30,15 +31,19 @@ export interface HttpClient {
|
|
|
30
31
|
*/
|
|
31
32
|
get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
32
33
|
/**
|
|
33
|
-
* Makes a POST request.
|
|
34
|
+
* Makes a POST request. `data` is the request BODY, not a config object: the wire body is
|
|
35
|
+
* `data` itself, so `post(url, { data: body })` sends `{"data":body}` — pass `body` directly.
|
|
36
|
+
* A config (headers, params) is the THIRD argument.
|
|
34
37
|
*/
|
|
35
38
|
post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
36
39
|
/**
|
|
37
|
-
* Makes a PUT request.
|
|
40
|
+
* Makes a PUT request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
41
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
38
42
|
*/
|
|
39
43
|
put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
40
44
|
/**
|
|
41
|
-
* Makes a PATCH request.
|
|
45
|
+
* Makes a PATCH request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
46
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
42
47
|
*/
|
|
43
48
|
patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>;
|
|
44
49
|
/**
|
|
@@ -98,7 +103,10 @@ export interface HttpClientConfig {
|
|
|
98
103
|
/**
|
|
99
104
|
* The scheme of the `Authorization` header the auth token is sent with:
|
|
100
105
|
* `Bearer` (default), or what your API expects, e.g. `Token` for an API that
|
|
101
|
-
* reads `Authorization: Token <jwt>`.
|
|
106
|
+
* reads `Authorization: Token <jwt>`. It is an option of the client's
|
|
107
|
+
* CONSTRUCTOR (`createFetchClient({ baseURL, authScheme: 'Token' })`, or the
|
|
108
|
+
* bonded provider's `createAxiosClient({ … })`), never a property of the client
|
|
109
|
+
* it returns.
|
|
102
110
|
*/
|
|
103
111
|
authScheme?: string;
|
|
104
112
|
}
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAClG,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEhF;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEtC
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAClG,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEhF;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEtC;;;OAGG;IACH,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzE;;OAEG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAE/E;;;;OAIG;IACH,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAEhG;;;OAGG;IACH,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAE/F;;;OAGG;IACH,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAEjG;;OAEG;IACH,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA;IAElF;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAA;IAElE;;;OAGG;IACH,sBAAsB,CAAC,WAAW,EAAE,mBAAmB,GAAG,MAAM,IAAI,CAAA;IAEpE;;;OAGG;IACH,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,GAAG,MAAM,IAAI,CAAA;IAE9D;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAExC;;OAEG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI,CAAA;IAE7B;;;;OAIG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEvC;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IAEzB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
* Provides a unified HTTP client API that works across different
|
|
5
5
|
* HTTP libraries (fetch, axios, ky, etc.).
|
|
6
6
|
*
|
|
7
|
+
* **The body is the SECOND argument: `post(url, data, config?)` — likewise `put` and `patch`,
|
|
8
|
+
* and the response is `HttpResponse<T>` (read `.data` for the body).** `data` IS the request
|
|
9
|
+
* body; a plain object is serialized as the JSON body. Passing `{ data: body }` there is NOT a
|
|
10
|
+
* config object — it makes the wire body `{"data":{…}}`, so the API sees an object whose only
|
|
11
|
+
* key is `data`, finds none of the fields it validates, and answers
|
|
12
|
+
* `422 {"errors":{"username":["can't be blank"],…}}`. Write `post('/users', { user })`, never
|
|
13
|
+
* `post('/users', { data: { user } })`. The config object (headers, params, timeout,
|
|
14
|
+
* `skipAuthGate`) is the THIRD argument. Only `request({ method, url, data, … })` takes `data`
|
|
15
|
+
* inside an options object, because there that object IS the config.
|
|
16
|
+
*
|
|
7
17
|
* @example
|
|
8
18
|
* ```tsx
|
|
9
19
|
* // In a React component, get the configured client from context and call it.
|
|
@@ -17,7 +27,10 @@
|
|
|
17
27
|
* const res = await http.get<Plant[]>('/plants') // baseURL ('/api') is prepended
|
|
18
28
|
* setPlants(res.data)
|
|
19
29
|
* }
|
|
20
|
-
* //
|
|
30
|
+
* // Body-carrying verbs take the body as the SECOND argument:
|
|
31
|
+
* // http.post('/plants', plant) — wire body is `plant`
|
|
32
|
+
* // http.post('/plants', { data: plant }) — WRONG: wire body is `{"data": plant}`
|
|
33
|
+
* // http.put(url, body), http.patch(url, body) and http.delete(url) are also available.
|
|
21
34
|
* }
|
|
22
35
|
* ```
|
|
23
36
|
*
|
|
@@ -41,8 +54,12 @@
|
|
|
41
54
|
* Auth (the bearer token / session cookie) is attached by the client's interceptors — do not
|
|
42
55
|
* read a token from `localStorage` or hand-attach it (the token is memory-only; see the user
|
|
43
56
|
* resource).
|
|
44
|
-
* An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`)
|
|
45
|
-
* `authScheme: 'Token'`
|
|
57
|
+
* An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`) passes
|
|
58
|
+
* `authScheme: 'Token'` to the client's CONSTRUCTOR — `setClient(createFetchClient({ baseURL,
|
|
59
|
+
* authScheme: 'Token' }))`, or the bonded provider's constructor
|
|
60
|
+
* (`createAxiosClient({ … })` from `@molecule/app-http-axios`). It is NOT a property of
|
|
61
|
+
* `getClient()`'s result: that is a built client, and `client.authScheme = 'Token'` is a type
|
|
62
|
+
* error (TS2339) that changes no header. Do not hand-write a fetch wrapper for the scheme either.
|
|
46
63
|
*
|
|
47
64
|
* A request made while the session is still being restored WAITS for that restore, so a page
|
|
48
65
|
* that fetches viewer-dependent data on mount (a profile's `following` flag, a feed, a
|
|
@@ -51,6 +68,14 @@
|
|
|
51
68
|
* `@molecule/app-bonds-default-react` get it without doing anything. An app with its own session
|
|
52
69
|
* module registers its own: `setAuthGate(() => session.whenRestored())`.
|
|
53
70
|
*
|
|
71
|
+
* **A request the gate itself depends on must opt out of it: pass `skipAuthGate: true`.** A gate
|
|
72
|
+
* that waits for a session restore whose own request goes through this client waits on itself —
|
|
73
|
+
* that request is held by the gate waiting for it, so the restore never settles and every request
|
|
74
|
+
* the gate holds stalls until it times out (3 s). The request that restores the session for a gate
|
|
75
|
+
* you registered yourself is therefore written
|
|
76
|
+
* `http.get(currentUserEndpoint, { skipAuthGate: true })`; `@molecule/app-auth`'s own restore does
|
|
77
|
+
* not need it (it calls `fetch`, not this client).
|
|
78
|
+
*
|
|
54
79
|
* @module
|
|
55
80
|
*/
|
|
56
81
|
export * from './auth-gate.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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH,cAAc,gBAAgB,CAAA;AAC9B,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
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
* Provides a unified HTTP client API that works across different
|
|
5
5
|
* HTTP libraries (fetch, axios, ky, etc.).
|
|
6
6
|
*
|
|
7
|
+
* **The body is the SECOND argument: `post(url, data, config?)` — likewise `put` and `patch`,
|
|
8
|
+
* and the response is `HttpResponse<T>` (read `.data` for the body).** `data` IS the request
|
|
9
|
+
* body; a plain object is serialized as the JSON body. Passing `{ data: body }` there is NOT a
|
|
10
|
+
* config object — it makes the wire body `{"data":{…}}`, so the API sees an object whose only
|
|
11
|
+
* key is `data`, finds none of the fields it validates, and answers
|
|
12
|
+
* `422 {"errors":{"username":["can't be blank"],…}}`. Write `post('/users', { user })`, never
|
|
13
|
+
* `post('/users', { data: { user } })`. The config object (headers, params, timeout,
|
|
14
|
+
* `skipAuthGate`) is the THIRD argument. Only `request({ method, url, data, … })` takes `data`
|
|
15
|
+
* inside an options object, because there that object IS the config.
|
|
16
|
+
*
|
|
7
17
|
* @example
|
|
8
18
|
* ```tsx
|
|
9
19
|
* // In a React component, get the configured client from context and call it.
|
|
@@ -17,7 +27,10 @@
|
|
|
17
27
|
* const res = await http.get<Plant[]>('/plants') // baseURL ('/api') is prepended
|
|
18
28
|
* setPlants(res.data)
|
|
19
29
|
* }
|
|
20
|
-
* //
|
|
30
|
+
* // Body-carrying verbs take the body as the SECOND argument:
|
|
31
|
+
* // http.post('/plants', plant) — wire body is `plant`
|
|
32
|
+
* // http.post('/plants', { data: plant }) — WRONG: wire body is `{"data": plant}`
|
|
33
|
+
* // http.put(url, body), http.patch(url, body) and http.delete(url) are also available.
|
|
21
34
|
* }
|
|
22
35
|
* ```
|
|
23
36
|
*
|
|
@@ -41,8 +54,12 @@
|
|
|
41
54
|
* Auth (the bearer token / session cookie) is attached by the client's interceptors — do not
|
|
42
55
|
* read a token from `localStorage` or hand-attach it (the token is memory-only; see the user
|
|
43
56
|
* resource).
|
|
44
|
-
* An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`)
|
|
45
|
-
* `authScheme: 'Token'`
|
|
57
|
+
* An API that wants another scheme than `Bearer` (`Authorization: Token <jwt>`) passes
|
|
58
|
+
* `authScheme: 'Token'` to the client's CONSTRUCTOR — `setClient(createFetchClient({ baseURL,
|
|
59
|
+
* authScheme: 'Token' }))`, or the bonded provider's constructor
|
|
60
|
+
* (`createAxiosClient({ … })` from `@molecule/app-http-axios`). It is NOT a property of
|
|
61
|
+
* `getClient()`'s result: that is a built client, and `client.authScheme = 'Token'` is a type
|
|
62
|
+
* error (TS2339) that changes no header. Do not hand-write a fetch wrapper for the scheme either.
|
|
46
63
|
*
|
|
47
64
|
* A request made while the session is still being restored WAITS for that restore, so a page
|
|
48
65
|
* that fetches viewer-dependent data on mount (a profile's `following` flag, a feed, a
|
|
@@ -51,6 +68,14 @@
|
|
|
51
68
|
* `@molecule/app-bonds-default-react` get it without doing anything. An app with its own session
|
|
52
69
|
* module registers its own: `setAuthGate(() => session.whenRestored())`.
|
|
53
70
|
*
|
|
71
|
+
* **A request the gate itself depends on must opt out of it: pass `skipAuthGate: true`.** A gate
|
|
72
|
+
* that waits for a session restore whose own request goes through this client waits on itself —
|
|
73
|
+
* that request is held by the gate waiting for it, so the restore never settles and every request
|
|
74
|
+
* the gate holds stalls until it times out (3 s). The request that restores the session for a gate
|
|
75
|
+
* you registered yourself is therefore written
|
|
76
|
+
* `http.get(currentUserEndpoint, { skipAuthGate: true })`; `@molecule/app-auth`'s own restore does
|
|
77
|
+
* not need it (it calls `fetch`, not this client).
|
|
78
|
+
*
|
|
54
79
|
* @module
|
|
55
80
|
*/
|
|
56
81
|
export * from './auth-gate.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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AAEH,cAAc,gBAAgB,CAAA;AAC9B,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;AAK/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;AAK/D;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAQ,gBAAqB,KAAG,UA+VjE,CAAA"}
|
package/dist/provider.js
CHANGED
|
@@ -53,7 +53,9 @@ export const createFetchClient = (config = {}) => {
|
|
|
53
53
|
// Wait for the session restore before anything else: the interceptors below
|
|
54
54
|
// read the auth token, and the request must not leave unauthenticated just
|
|
55
55
|
// because a page effect ran before the restore settled (see auth-gate.ts).
|
|
56
|
-
|
|
56
|
+
// The request config goes with it so a request the gate itself depends on can opt out
|
|
57
|
+
// (`skipAuthGate`) and a stalled gate can name what it held.
|
|
58
|
+
await awaitAuthGate(requestConfig);
|
|
57
59
|
// Apply request interceptors
|
|
58
60
|
let finalConfig = { ...requestConfig };
|
|
59
61
|
for (const interceptor of requestInterceptors) {
|
package/dist/provider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAA;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAI9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,SAA2B,EAAE,EAAc,EAAE;IAC7E,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,SAAS,GAAkB,IAAI,CAAA;IACnC,MAAM,mBAAmB,GAAyB,EAAE,CAAA;IACpD,MAAM,oBAAoB,GAA0B,EAAE,CAAA;IACtD,MAAM,iBAAiB,GAAuB,EAAE,CAAA;IAChD,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAc,CAAA;IAE/C,kEAAkE;IAClE,0DAA0D;IAC1D,kEAAkE;IAClE,uEAAuE;IACvE,oEAAoE;IACpE,2CAA2C;IAC3C,IAAI,oBAAoB,GAAG,KAAK,CAAA;IAChC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACnF,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,oBAAoB,GAAG,IAAI,CAAA;YAC3B,gEAAgE;YAChE,8DAA8D;YAC9D,2DAA2D;YAC3D,UAAU,CAAC,GAAG,EAAE;gBACd,oBAAoB,GAAG,KAAK,CAAA;YAC9B,CAAC,EAAE,IAAI,CAAC,CAAA;QACV,CAAC,CAAA;QACD,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;QAChD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAED,MAAM,MAAM,GAAe;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;QAC7B,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,EAAE;QAE3C,KAAK,CAAC,OAAO,CAAc,aAAgC;YACzD,4EAA4E;YAC5E,2EAA2E;YAC3E,2EAA2E;YAC3E,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -27,6 +27,25 @@ export interface RequestConfig {
|
|
|
27
27
|
* Whether to include credentials (cookies).
|
|
28
28
|
*/
|
|
29
29
|
withCredentials?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Send this request WITHOUT waiting for the session restore (the auth gate).
|
|
32
|
+
*
|
|
33
|
+
* A request the gate itself depends on must set this. A gate registered with
|
|
34
|
+
* `setAuthGate` that waits for a session restore whose own request goes through this
|
|
35
|
+
* client otherwise waits on itself: the gate holds the restore's request, the restore's
|
|
36
|
+
* promise never settles, and every request on the page stalls until the gate times out —
|
|
37
|
+
* so pass `skipAuthGate: true` on the restore's own request:
|
|
38
|
+
*
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // the request the gate's restore makes, through the same client the gate holds back
|
|
41
|
+
* await http.get(currentUserEndpoint, { skipAuthGate: true })
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* `@molecule/app-auth`'s own restore does not need it — it sends its request with
|
|
45
|
+
* `fetch`, not through this client. An app with its own session store that registers a
|
|
46
|
+
* gate with `setAuthGate` does.
|
|
47
|
+
*/
|
|
48
|
+
skipAuthGate?: boolean;
|
|
30
49
|
/**
|
|
31
50
|
* Response type.
|
|
32
51
|
*/
|
|
@@ -36,7 +55,11 @@ export interface RequestConfig {
|
|
|
36
55
|
*/
|
|
37
56
|
signal?: AbortSignal;
|
|
38
57
|
/**
|
|
39
|
-
* Request body data
|
|
58
|
+
* Request body data, as a field of THIS config object — the `request({ method, url, data })`
|
|
59
|
+
* form. The verb methods take the body as their SECOND argument: `post(url, data, config)`,
|
|
60
|
+
* `put(url, data, config)`, `patch(url, data, config)`. Never wrap it there as
|
|
61
|
+
* `{ data: body }`: that object is the body, so the wire sends `{"data":body}` and the API
|
|
62
|
+
* sees none of the fields at its top level.
|
|
40
63
|
*/
|
|
41
64
|
data?: unknown;
|
|
42
65
|
/**
|
|
@@ -44,6 +67,29 @@ export interface RequestConfig {
|
|
|
44
67
|
*/
|
|
45
68
|
options?: Record<string, unknown>;
|
|
46
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* What the auth gate is told about the request it is about to hold: whether the request
|
|
72
|
+
* opts out of the wait, and how to name it in the stalled-gate report.
|
|
73
|
+
*
|
|
74
|
+
* A request's own `RequestConfig` satisfies this — the providers pass it straight through
|
|
75
|
+
* (`awaitAuthGate(requestConfig)`), so a provider never has to build one by hand.
|
|
76
|
+
*/
|
|
77
|
+
export interface AuthGateRequest {
|
|
78
|
+
/**
|
|
79
|
+
* Send this request without waiting for the gate at all — see
|
|
80
|
+
* `RequestConfig.skipAuthGate`.
|
|
81
|
+
*/
|
|
82
|
+
skipAuthGate?: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* The request's HTTP method, for the message logged when the gate never settles.
|
|
85
|
+
*/
|
|
86
|
+
method?: string;
|
|
87
|
+
/**
|
|
88
|
+
* The request's URL, for the message logged when the gate never settles. A URL may carry
|
|
89
|
+
* an id; it never carries a credential (tokens travel in headers).
|
|
90
|
+
*/
|
|
91
|
+
url?: string;
|
|
92
|
+
}
|
|
47
93
|
/**
|
|
48
94
|
* Full request configuration including method and URL.
|
|
49
95
|
*/
|
|
@@ -57,7 +103,7 @@ export interface FullRequestConfig extends RequestConfig {
|
|
|
57
103
|
*/
|
|
58
104
|
url: string;
|
|
59
105
|
/**
|
|
60
|
-
* Request body data.
|
|
106
|
+
* Request body data — a field of this config object, never a second argument here.
|
|
61
107
|
*/
|
|
62
108
|
data?: unknown;
|
|
63
109
|
}
|
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;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAA;IAEvD;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IAEpB
|
|
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;;;;;;;;;;;;;;;;;OAiBG;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;;GAEG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAGzB,MAAM,EAAE,MAAM;IACd,QAAQ,CAAC,EAAE,YAAY;IACvB,MAAM,CAAC,EAAE,iBAAiB;IAC1B,QAAQ,CAAC,EAAE,MAAM;gBAJxB,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;CAK3B"}
|
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;AAwJH;;GAEG;AACH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAGzB;IACA;IACA;IACA;IALT,YACE,OAAe,EACR,MAAc,EACd,QAAuB,EACvB,MAA0B,EAC1B,QAAiB;QAExB,KAAK,CAAC,OAAO,CAAC,CAAA;QALP,WAAM,GAAN,MAAM,CAAQ;QACd,aAAQ,GAAR,QAAQ,CAAe;QACvB,WAAM,GAAN,MAAM,CAAoB;QAC1B,aAAQ,GAAR,QAAQ,CAAS;QAGxB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAA;IACzB,CAAC;CACF"}
|
package/dist/utilities.d.ts
CHANGED
|
@@ -39,9 +39,13 @@ export declare const get: <T = unknown>(url: string, config?: RequestConfig) =>
|
|
|
39
39
|
/**
|
|
40
40
|
* Makes a POST request using the bonded HTTP client.
|
|
41
41
|
*
|
|
42
|
+
* The body is `data` — the SECOND argument. `post(url, { data: body })` sends the JSON body
|
|
43
|
+
* `{"data":body}`, not `body`, so the API finds none of its fields at the top level; pass the
|
|
44
|
+
* body directly (`post('/users', { user })`). The config is the THIRD argument.
|
|
45
|
+
*
|
|
42
46
|
* @param url - The request URL.
|
|
43
|
-
* @param data - The request body.
|
|
44
|
-
* @param config - Optional request configuration.
|
|
47
|
+
* @param data - The request body itself (never `{ data: body }`).
|
|
48
|
+
* @param config - Optional request configuration (headers, params, timeout).
|
|
45
49
|
* @returns The HTTP response with typed data.
|
|
46
50
|
*/
|
|
47
51
|
export declare const post: <T = unknown>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>;
|
|
@@ -49,8 +53,10 @@ export declare const post: <T = unknown>(url: string, data?: unknown, config?: R
|
|
|
49
53
|
* Makes a PUT request using the bonded HTTP client.
|
|
50
54
|
*
|
|
51
55
|
* @param url - The request URL.
|
|
52
|
-
*
|
|
53
|
-
*
|
|
56
|
+
* The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
57
|
+
*
|
|
58
|
+
* @param data - The request body itself.
|
|
59
|
+
* @param config - Optional request configuration (the third argument).
|
|
54
60
|
* @returns The HTTP response with typed data.
|
|
55
61
|
*/
|
|
56
62
|
export declare const put: <T = unknown>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>;
|
|
@@ -58,8 +64,10 @@ export declare const put: <T = unknown>(url: string, data?: unknown, config?: Re
|
|
|
58
64
|
* Makes a PATCH request using the bonded HTTP client.
|
|
59
65
|
*
|
|
60
66
|
* @param url - The request URL.
|
|
61
|
-
*
|
|
62
|
-
*
|
|
67
|
+
* The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
68
|
+
*
|
|
69
|
+
* @param data - The request body itself (the partial update).
|
|
70
|
+
* @param config - Optional request configuration (the third argument).
|
|
63
71
|
* @returns The HTTP response with typed data.
|
|
64
72
|
*/
|
|
65
73
|
export declare const patch: <T = unknown>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>;
|
package/dist/utilities.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAI7D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,UAAU,KAAG,IAE9C,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,UAM5B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,GAAG,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,aAAa,KAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAC7D,CAAA;AAEjC
|
|
1
|
+
{"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAI7D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,UAAU,KAAG,IAE9C,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,QAAO,UAM5B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,GAAG,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,aAAa,KAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAC7D,CAAA;AAEjC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,GAAG,OAAO,EAC9B,KAAK,MAAM,EACX,OAAO,OAAO,EACd,SAAS,aAAa,KACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAA2C,CAAA;AAErE;;;;;;;;;GASG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,GAAG,OAAO,EAC7B,KAAK,MAAM,EACX,OAAO,OAAO,EACd,SAAS,aAAa,KACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAA0C,CAAA;AAEpE;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,GAAG,OAAO,EAC/B,KAAK,MAAM,EACX,OAAO,OAAO,EACd,SAAS,aAAa,KACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAA4C,CAAA;AAEtE;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,GAAI,CAAC,GAAG,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,aAAa,KAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAC1D,CAAA;AAEpC;;;GAGG;AACH,eAAO,MAAM,WAAW,mBAA4D,CAAA"}
|
package/dist/utilities.js
CHANGED
|
@@ -49,9 +49,13 @@ export const get = (url, config) => getClient().get(url, config);
|
|
|
49
49
|
/**
|
|
50
50
|
* Makes a POST request using the bonded HTTP client.
|
|
51
51
|
*
|
|
52
|
+
* The body is `data` — the SECOND argument. `post(url, { data: body })` sends the JSON body
|
|
53
|
+
* `{"data":body}`, not `body`, so the API finds none of its fields at the top level; pass the
|
|
54
|
+
* body directly (`post('/users', { user })`). The config is the THIRD argument.
|
|
55
|
+
*
|
|
52
56
|
* @param url - The request URL.
|
|
53
|
-
* @param data - The request body.
|
|
54
|
-
* @param config - Optional request configuration.
|
|
57
|
+
* @param data - The request body itself (never `{ data: body }`).
|
|
58
|
+
* @param config - Optional request configuration (headers, params, timeout).
|
|
55
59
|
* @returns The HTTP response with typed data.
|
|
56
60
|
*/
|
|
57
61
|
export const post = (url, data, config) => getClient().post(url, data, config);
|
|
@@ -59,8 +63,10 @@ export const post = (url, data, config) => getClient().post(url, data, config);
|
|
|
59
63
|
* Makes a PUT request using the bonded HTTP client.
|
|
60
64
|
*
|
|
61
65
|
* @param url - The request URL.
|
|
62
|
-
*
|
|
63
|
-
*
|
|
66
|
+
* The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
67
|
+
*
|
|
68
|
+
* @param data - The request body itself.
|
|
69
|
+
* @param config - Optional request configuration (the third argument).
|
|
64
70
|
* @returns The HTTP response with typed data.
|
|
65
71
|
*/
|
|
66
72
|
export const put = (url, data, config) => getClient().put(url, data, config);
|
|
@@ -68,8 +74,10 @@ export const put = (url, data, config) => getClient().put(url, data, config);
|
|
|
68
74
|
* Makes a PATCH request using the bonded HTTP client.
|
|
69
75
|
*
|
|
70
76
|
* @param url - The request URL.
|
|
71
|
-
*
|
|
72
|
-
*
|
|
77
|
+
* The body is `data` — the SECOND argument, never `{ data: body }`.
|
|
78
|
+
*
|
|
79
|
+
* @param data - The request body itself (the partial update).
|
|
80
|
+
* @param config - Optional request configuration (the third argument).
|
|
73
81
|
* @returns The HTTP response with typed data.
|
|
74
82
|
*/
|
|
75
83
|
export const patch = (url, data, config) => getClient().patch(url, data, config);
|
package/dist/utilities.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjD,MAAM,SAAS,GAAG,aAAa,CAAA;AAE/B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAQ,EAAE;IACpD,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;AACzB,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAe,EAAE;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAa,SAAS,CAAC,CAAA;IAC/C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAA;IACpC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACzB,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAc,GAAW,EAAE,MAAsB,EAA4B,EAAE,CAChG,SAAS,EAAE,CAAC,GAAG,CAAI,GAAG,EAAE,MAAM,CAAC,CAAA;AAEjC
|
|
1
|
+
{"version":3,"file":"utilities.js","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAGzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGjD,MAAM,SAAS,GAAG,aAAa,CAAA;AAE/B;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAkB,EAAQ,EAAE;IACpD,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;AACzB,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,GAAe,EAAE;IACxC,MAAM,QAAQ,GAAG,OAAO,CAAa,SAAS,CAAC,CAAA;IAC/C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAA;IACpC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;IACzB,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAc,GAAW,EAAE,MAAsB,EAA4B,EAAE,CAChG,SAAS,EAAE,CAAC,GAAG,CAAI,GAAG,EAAE,MAAM,CAAC,CAAA;AAEjC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,GAAW,EACX,IAAc,EACd,MAAsB,EACI,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,CAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AAErE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CACjB,GAAW,EACX,IAAc,EACd,MAAsB,EACI,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,CAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AAEpE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CACnB,GAAW,EACX,IAAc,EACd,MAAsB,EACI,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,CAAI,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AAEtE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAc,GAAW,EAAE,MAAsB,EAA4B,EAAE,CAChG,SAAS,EAAE,CAAC,MAAM,CAAI,GAAG,EAAE,MAAM,CAAC,CAAA;AAEpC;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA"}
|