Skip to content

Core API

Eugene Lazutkin edited this page Jul 1, 2026 · 7 revisions

Core API — io

The default export io is the whole library: a callable, the verbs, and the modifier namespaces (io.full, io.stream) and services (io.cache, io.track, …).

import io from 'double-meh';

const data = await io.get('https://api.example.com/x');

Verbs

get, head, post, put, patch, delete (+ del / remove aliases), options — as methods on io and as named ESM exports. Exotic verbs via io.makeVerb('REPORT').

Signature: verb(url, data?, options?).

  • url — a string, a URL, or an options bag (a reusable endpoint descriptor).
  • data — the frequent optional: the query for reads, the body for writes.
  • options — the rare override bag (as, ifMatch, stream, cache, fetch, …), typed to exclude url.

For reads, null/undefined data → no query. For writes, undefined → no body, but null is a valid JSON-null body. See Requests & options.

Return model — the method declares the shape

Call Returns
io.get(url) (any bare verb) the parsed data
io.full.get(url) the full envelope {data, status, ok, headers, response, …}
io.stream.get(url) a Web ReadableStream (GET-only) — see Streaming
ios.put(url, opts) a streaming {readable, writable, response} duplex
io.head(url) / io.options(url) derived metadata (no body)

The bare verb is the envelope's .data: io.get(url)(await io.full.get(url)).data. Options tune behavior, never the return type.

The callable io and endpoint descriptors

io(options) is the low-level callable; the verbs are sugar. Because url may be an options bag, a reusable endpoint is natural — the bag is spread (never mutated), and the 3rd arg overrides it per call (scalars replace; headers/query merge per key; url stays from the 1st arg):

const endpoint = {url: '/things/7', headers: {authorization: token}};
await io.get(endpoint);                       // GET with the auth header
await io.put(endpoint, body, {ifMatch: tag}); // reuse it for a conditional PUT

Services & extensibility

io carries the services and the registration seams:

  • Services: cache, track, retry, mock — each with .attach() / .detach() and per-request opt-in flags.
  • Inspectors: io.inspect.request(fn) and io.inspect.response(fn) rewrite requests / envelopes (see Cookbook: requests & responses).
  • Processors: io.registerData(processor) (encode request bodies by type), io.registerMime(processor) (decode responses by content-type).
  • Transports: io.registerTransport(name, fn), io.defaultTransport — see fetch transport.
  • MIME registry: io.mimeTypes — the mutable alias table behind the as option.

Low-level helpers

io.run(options) / io.request(options) (the raw pipeline, returns the envelope), io.toEnvelope(response, options) (wrap a Response you already have), io.makeKey(options) / io.buildUrl(options) (see keys & URLs), io.makeVerb(method).

See also

Clone this wiki locally