-
Notifications
You must be signed in to change notification settings - Fork 0
Concepts: the pipeline
Every request flows through one pipeline. Knowing the order is how you know where to hook in — the whole point of the library is to make that setup cheap so calls stay trivial.
-
Normalize — merge
url/data/optionsinto one options object. -
Prepare — build the URL (keys & URLs), headers, and body (
encodeBody). -
Request inspectors — matching
io.inspect.request(fn, match?)entries may rewrite the prepared request. -
Key — the canonical request key (
io.makeKey) for dedup / cache lookups. - Dedup — track, in the core (not a service): an identical in-flight GET is joined instead of re-run.
- Services onion — each attached service (by priority) may short-circuit (cache hit, mock) or pass through, wrapping the transport.
-
Transport —
fetchby default (fetch transport). -
Decode — parse the body by content-type (or as forced by the
decodeoption), or hand back the raw stream for{stream: true}. -
Envelope — build the response envelope; run matching response
inspectors (
io.inspect.response(fn, match?)); throwBadStatuson a non-2xx (unlessignoreBadStatus).
Everything extensible threads through this one flow:
| Seam | Register with | Runs at |
|---|---|---|
| Request inspector | io.inspect.request(fn, match?) |
3 — rewrite the outgoing request |
| Response inspector | io.inspect.response(fn, match?) |
9 — post-process / replace the envelope |
| Data processor | io.registerData(p) |
2 — encode a request body by type |
| MIME processor | io.registerMime(p) |
8 — decode a response by content-type |
| Service |
io.attach(service) / io.detach(name)
|
6 — short-circuit or wrap the transport |
| Transport | io.registerTransport(name, fn) |
7 — swap the network layer |
Inspectors are scoped: the optional match is a URL prefix string, a RegExp, or a predicate
(url) => boolean, and the inspector runs only for matching request URLs — the registries
(io.requestInspectors / io.responseInspectors) hold {fn, match} entries.
Services carry a priority (higher wraps outermost), so cache,
retry, and mock compose as one onion. Participation is decided
per request: a per-request flag (cache: false, retry: …, mock: false, track: true) wins when
present; where a facility ships a default set (io.cache.theDefault, io.track.theDefault — a
boolean or a predicate (options) => boolean, shipped as options => !options.transport), it
governs the rest.
The pipeline reports through events (io.on / io.off / io.emit): 'request'
(request, ctx) when a run starts, 'success' (envelope, ctx), 'failure' (error, ctx),
'retry' ({attempt, response, error}, ctx) per retry attempt, and a one-time 'ready' after the
code-forward drain. io.inFlight counts active runs. A cache hit still
runs the pipeline, so it emits request / success.
- Core API · cache · fetch transport · events · Return model
Guides
Concepts
Services
Modules
- fetch transport
- keys & URLs
- helpers
- records
- sse
- storage backends
- compression encoders
- Service Worker integration
Cookbook