Skip to content

v0.53.4

Choose a tag to compare

@github-actions github-actions released this 26 Apr 07:34
· 4 commits to main since this release

🌟 v0.53.4 — Meet the misina link

This release adds a brand-new HTTP transport for the Silgi client, sitting side-by-side with the existing ofetch link. Nothing in your existing code changes — silgi/client/ofetch keeps working exactly as before. The new silgi/client/misina is purely additive, opt-in, and built for teams that want stricter retry and error semantics out of the box.

✨ What's new

silgi/client/misina — a second link adapter

Powered by misina, a zero-dependency, fetch-first HTTP client. Same createLink({ url, headers, retry, timeout, protocol }) shape you already know, with a few new tricks:

import { createClient } from 'silgi/client'
import { createLink } from 'silgi/client/misina'

const link = createLink({
  url: 'http://localhost:3000',
  retry: 2,
  idempotencyKey: 'auto',
})

const client = createClient<AppRouter>(link)

Why you might pick it

  • Retry-After & RateLimit-Reset parsing — when the server signals a delay, the link honors it instead of using your fixed backoff.
  • Distinct error classesHTTPError (server returned an error status), NetworkError (DNS, connection reset, offline), and TimeoutError (per-attempt or wall-clock budget exceeded). All still surface as SilgiError for catch-by-code, so your existing error handling keeps working.
  • Idempotency-Key auto-generation — retried POST / PATCH / DELETE calls send the same Idempotency-Key across attempts so the server can deduplicate. Set idempotencyKey: 'auto' to opt in.
  • Wall-clock timeouttimeout caps each attempt, totalTimeout caps the whole logical call (including retry delays).
  • Redirect security — sensitive headers are stripped on cross-origin redirects, and https → http downgrades are refused.
  • Lifecycle hooksbeforeRequest, afterResponse, beforeError, and a terminal onComplete that fires exactly once per logical call (perfect for tracing & metrics).

Retry with backoff

const link = createLink({
  url: 'http://localhost:3000',
  retry: {
    limit: 3,
    delay: (attempt) => 0.3 * 2 ** (attempt - 1) * 1000, // 300ms, 600ms, 1200ms
    backoffLimit: 30_000,
    jitter: true,
    statusCodes: [408, 429, 500, 502, 503, 504],
  },
})

Re-exports

A new silgi/misina subpath re-exports the upstream package, mirroring the existing silgi/ofetch ergonomics — so you can grab misina's typed errors and helpers directly from Silgi:

import { isHTTPError, isNetworkError, isTimeoutError } from 'silgi/misina'

📚 Docs

  • Full new "misina link" section in the Client docs — options table, retry-with-backoff, hooks, and trade-offs vs ofetch.

🤝 Compatibility

  • Zero breaking changes. The default link is still silgi/client/ofetch.
  • Both links produce the same SilgiError instances on failure — switching transports doesn't change your catch logic.
  • Same wire protocols (json / messagepack / devalue), same SSE subscription support, same per-call signal.

🙏 Which one should I use?

  • Stick with ofetch if you're already happy, deploying to Nuxt/h3, or want the most battle-tested option.
  • Try misina if you care about retry correctness on rate-limited APIs, want explicit NetworkError vs HTTPError discrimination, or need idempotency keys for retried mutations.

You can even mix both via DynamicLink if different parts of your API live behind different services.

Full Changelog: v0.53.3...v0.53.4