22
33Use ` createClient ` to create a reusable HTTP client instance.
44
5+ It provides a consistent way to configure:
6+
7+ - base URL and default headers
8+ - timeouts and retries
9+ - auth
10+ - lifecycle hooks
11+ - request observability metadata
12+
513## Basic client
614
715``` ts
816import { createClient } from ' @dfsync/client' ;
917
1018const client = createClient ({
11- baseURL : ' https://api.example.com' ,
19+ baseUrl : ' https://api.example.com' ,
1220});
1321```
1422
@@ -59,6 +67,20 @@ type ClientConfig = {
5967};
6068```
6169
70+ Hook configuration supports:
71+
72+ - ` beforeRequest `
73+ - ` afterResponse `
74+ - ` onError `
75+ - ` onRetry `
76+
77+ Retry configuration supports:
78+
79+ - retry attempts
80+ - retry conditions
81+ - backoff strategy
82+ - ` Retry-After ` handling
83+
6284## HTTP methods
6385
6486The client provides a predictable set of methods:
@@ -146,6 +168,10 @@ type RequestOptions = {
146168};
147169```
148170
171+ ` requestId ` can be provided explicitly when you want to correlate logs or trace a request across services.
172+
173+ Request-level ` retry ` overrides client-level retry settings.
174+
149175## Low-level request
150176
151177``` ts
@@ -155,13 +181,13 @@ const result = await client.request({
155181 body: {
156182 type: ' user.created' ,
157183 },
158- headers: {
159- ' x-request-id' : ' req-123' ,
160- },
184+ requestId: ' req-123' ,
161185 timeout: 3000 ,
162186});
163187```
164188
189+ If both ` requestId ` and ` x-request-id ` header are provided, ` x-request-id ` takes precedence.
190+
165191### Request Config
166192
167193``` ts
@@ -180,14 +206,26 @@ type RequestConfig = {
180206
181207## Request context
182208
183- Each request is executed within a request context that contains:
209+ Each request attempt is executed within a request context that contains:
184210
185- - ` requestId ` — unique identifier for the request
186- - ` attempt ` — current retry attempt
211+ - ` requestId ` — stable identifier for the full request lifecycle
212+ - ` attempt ` — current retry attempt (zero-based)
213+ - ` maxAttempts ` — total number of allowed attempts, including the initial request
187214- ` signal ` — AbortSignal for cancellation
188215- ` startedAt ` — request start timestamp
189216
190- This context is available in all lifecycle hooks.
217+ Completed attempts may also expose:
218+
219+ - ` endedAt ` — request end timestamp
220+ - ` durationMs ` — total duration for the current attempt
221+
222+ Retry-specific contexts may also expose:
223+
224+ - ` retryDelayMs `
225+ - ` retryReason `
226+ - ` retrySource `
227+
228+ This context is available through lifecycle hooks.
191229
192230## Request ID
193231
@@ -196,9 +234,12 @@ Each request has a `requestId` that is:
196234- automatically generated by default
197235- can be overridden per request
198236- propagated via the ` x-request-id ` header
237+ - remains stable across retries
199238
200239This allows tracing requests across services.
201240
241+ It also makes retries easier to correlate in logs and monitoring systems.
242+
202243### Example
203244
204245``` ts
@@ -275,3 +316,50 @@ If request body is a string, the client:
275316
276317- sends it as-is
277318- does not force a ` content-type `
319+
320+ ## Retry observability
321+
322+ Retries can be observed using lifecycle hooks.
323+
324+ ``` ts
325+ const client = createClient ({
326+ baseUrl: ' https://api.example.com' ,
327+ retry: {
328+ attempts: 2 ,
329+ retryOn: [' 5xx' , ' 429' ],
330+ backoff: ' exponential' ,
331+ baseDelayMs: 300 ,
332+ },
333+ hooks: {
334+ onRetry({ requestId , attempt , maxAttempts , retryDelayMs , retryReason , retrySource }) {
335+ console .log ({
336+ requestId ,
337+ attempt ,
338+ maxAttempts ,
339+ retryDelayMs ,
340+ retryReason ,
341+ retrySource ,
342+ });
343+ },
344+ },
345+ });
346+ ```
347+
348+ This is useful for logging, monitoring, and debugging retry behavior.
349+
350+ ## Retry-After support
351+
352+ When a retryable response includes a ` Retry-After ` header, ` @dfsync/client ` uses that value before falling back to the configured backoff strategy.
353+
354+ Supported formats:
355+
356+ - seconds
357+ - HTTP-date
358+
359+ If the header value is invalid, ` @dfsync/client ` falls back to normal retry backoff.
360+
361+ ## Related guides
362+
363+ - See ** Hooks** for lifecycle hooks and observability metadata
364+ - See ** Retry** for retry conditions, backoff, and ` Retry-After `
365+ - See ** Errors** for failure behavior and error types
0 commit comments