You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**`@firekid/hurl`** is a modern, zero-dependency HTTP client for Node.js 18+, Cloudflare Workers, Vercel Edge Functions, Deno, and Bun — built on native fetch with retries, interceptors, auth helpers, in-memory caching, request deduplication, and full TypeScript support.
12
+
**`@firekid/hurl`** is a modern, zero-dependency HTTP client for Node.js 18+, Cloudflare Workers, Vercel Edge Functions, Deno, and Bun — built on native fetch with retries, interceptors, auth helpers, in-memory caching, request deduplication, SSE streaming, circuit breaker, and full TypeScript support.
13
13
14
14
```bash
15
15
npm install @firekid/hurl
@@ -34,6 +34,15 @@ const data = await hurl.get('/users', {
34
34
cache: { ttl: 60000 },
35
35
})
36
36
37
+
// Stream an AI response over SSE
38
+
const { close } =hurl.sse('https://api.openai.com/v1/chat/completions', {
Unlike the native `EventSource`, `hurl.sse()` works with POST requests, custom headers, and all auth types. This makes it directly compatible with AI APIs like OpenAI, Anthropic, and Gemini that stream over SSE.
195
+
196
+
```ts
197
+
const { close } =hurl.sse('https://api.openai.com/v1/chat/completions', {
`hurl.sse()` handles the `data: [DONE]` sentinel automatically — it fires `onDone` and closes the stream. You also get a `signal` option if you want to tie the stream to an `AbortController` you control.
235
+
236
+
---
237
+
238
+
## Circuit Breaker
239
+
240
+
The circuit breaker stops your app from hammering a failing service. After a set number of consecutive failures it opens the circuit and fast-fails all requests until a cooldown period passes, then lets one probe through to check if the service recovered.
The `proxy` option in `HurlRequestOptions` is reserved for a future release where this will be handled automatically.
306
-
307
-
---
308
431
---
309
432
310
433
## Parallel Requests
@@ -330,7 +453,7 @@ const api = hurl.create({
330
453
331
454
awaitapi.get('/users')
332
455
333
-
// Extend with overrides
456
+
// Extend with overrides — inherits parent interceptors
334
457
constadminApi=api.extend({
335
458
headers: { 'x-role': 'admin' }
336
459
})
@@ -340,9 +463,9 @@ const adminApi = api.extend({
340
463
341
464
## Error Handling
342
465
343
-
`hurl` throws a `HurlError` on HTTP errors (4xx/5xx), network failures, timeouts, aborts, and parse failures. It never resolves silently on bad status codes.
466
+
`hurl` throws a `HurlError` on HTTP errors (4xx/5xx), network failures, timeouts, aborts, parse failures, and open circuit breakers. It never resolves silently on bad status codes.
344
467
345
-
If you want to handle 4xx/5xx responses yourself without a try/catch, set `throwOnError: false` — the response will resolve normally and you can check `res.status` yourself.
468
+
Set `throwOnError: false` to receive 4xx/5xx responses without a throw:
@@ -460,7 +584,7 @@ Exports both ESM (`import`) and CommonJS (`require`).
460
584
461
585
## Why Not Axios?
462
586
463
-
**axios** is 35KB, has no native edge runtime support, no built-in retry, no deduplication, and carries `XMLHttpRequest` baggage from a different era of the web.
587
+
**axios** is 35KB, has no native edge runtime support, no built-in retry, no deduplication, no SSE, no circuit breaker, and carries `XMLHttpRequest` baggage from a different era of the web.
464
588
465
589
**got** dropped CommonJS in v12 — if your project uses `require()`, you're stuck on an old version.
466
590
@@ -486,16 +610,19 @@ Exports both ESM (`import`) and CommonJS (`require`).
486
610
| `hurl.head(url, options?)` | HEAD request → `Promise<HurlResponse<void>>` |
0 commit comments