@@ -60,30 +60,104 @@ client.request(config)
6060
6161## Main features
6262
63- - typed responses
63+ - predictable request lifecycle
64+ - request ID propagation (` x-request-id ` )
65+ - request cancellation via ` AbortSignal `
66+ - built-in retry with configurable policies
67+ - lifecycle hooks: ` beforeRequest ` , ` afterResponse ` , ` onError `
6468- request timeout support
69+
70+ - typed responses
6571- automatic JSON parsing
6672- consistent error handling
73+
6774- auth support: bearer, API key, custom
68- - lifecycle hooks: ` beforeRequest ` , ` afterResponse ` , ` onError `
6975- support for ` GET ` , ` POST ` , ` PUT ` , ` PATCH ` , and ` DELETE `
70- - retry policies
76+
77+ It provides a predictable and controllable HTTP request lifecycle for service-to-service communication.
7178
7279## How requests work
7380
74- A request in ` @dfsync/client ` follows this flow:
81+ A request in ` @dfsync/client ` follows a predictable lifecycle:
82+
83+ 1 . create request context
84+ 2 . build final URL from ` baseUrl ` , ` path ` , and optional query params
85+ 3 . merge client and request headers
86+ 4 . apply authentication
87+ 5 . attach request metadata (e.g. ` x-request-id ` )
88+ 6 . run ` beforeRequest ` hooks
89+ 7 . send request with ` fetch `
90+ 8 . retry on failure (if configured)
91+ 9 . parse response (JSON, text, or ` undefined ` for ` 204 ` )
92+ 10 . run ` afterResponse ` or ` onError ` hooks
93+
94+ ## Request context
95+
96+ Each request is executed within a request context that contains:
97+
98+ - ` requestId ` — unique identifier for the request
99+ - ` attempt ` — current retry attempt
100+ - ` signal ` — AbortSignal for cancellation
101+ - ` startedAt ` — request start timestamp
102+
103+ This context is available in all lifecycle hooks.
104+
105+ ## Request ID
106+
107+ Each request has a ` requestId ` that is:
108+
109+ - automatically generated by default
110+ - can be overridden per request
111+ - propagated via the ` x-request-id ` header
112+
113+ ### Example
114+
115+ ``` ts
116+ await client .get (' /users' , {
117+ requestId: ' req_123' ,
118+ });
119+ ```
120+
121+ You can also override the header directly:
122+
123+ ``` ts
124+ await client .get (' /users' , {
125+ headers: {
126+ ' x-request-id' : ' custom-id' ,
127+ },
128+ });
129+ ```
130+
131+ ## Request cancellation
132+
133+ Requests can be cancelled using ` AbortSignal ` :
134+
135+ ``` ts
136+ const controller = new AbortController ();
137+
138+ const promise = client .get (' /users' , {
139+ signal: controller .signal ,
140+ });
141+
142+ controller .abort ();
143+ ```
144+
145+ Cancellation is treated differently from timeouts:
146+
147+ - timeout → ` TimeoutError `
148+ - manual cancellation → ` RequestAbortedError `
149+
150+ ## Errors
151+
152+ dfsync provides structured error types:
153+
154+ - ` HttpError ` — non-2xx responses
155+ - ` NetworkError ` — network failures
156+ - ` TimeoutError ` — request timed out
157+ - ` RequestAbortedError ` — request was cancelled
75158
76- 1 . build final URL from ` baseUrl ` , ` path ` , and optional query params
77- 2 . merge default, client-level, and request-level headers
78- 3 . apply auth configuration
79- 4 . run ` beforeRequest ` hooks
80- 5 . send request with ` fetch `
81- 6 . if the request fails with a retryable error, retry according to the configured retry policy
82- 7 . parse response as JSON, text, or ` undefined ` for ` 204 `
83- 8 . throw structured errors for failed requests
84- 9 . run ` afterResponse ` or ` onError ` hooks
159+ This allows you to handle failures more precisely.
85160
86161## Roadmap
87162
88- See the project roadmap:
89- https://github.com/dfsyncjs/dfsync/blob/main/ROADMAP.md
163+ See the [ project roadmap] ( https://github.com/dfsyncjs/dfsync/blob/main/ROADMAP.md )
0 commit comments