Fetch
An effect-native HTTP client — the familiar `fetch`, wrapped as a chainable operation with codec-aware body decoding.
@ozaco/std/fetchstd:fetch wraps the platform fetch as an effect operation. fetch(input, init?) returns a FetchDef.Operation — a Future<Response> you can yield* for the wrapped response, or drive straight to a body with a chained shortcut like .json<T>(), .body<T>() or .stream<T>() (each runs the request and reads the body in one step).
Body reading integrates the registered std:codec: body<T>() decodes the whole payload through the codec (auto-installing JsonCodec if none is present), stream<T>() pipes the body through the codec's streaming decoder for one value per chunk, and raw() hands back the undecoded byte stream. The classic json/text/arrayBuffer/blob/formData/bytes readers are all present too.
Errors follow the Result convention. Thrown faults — network errors, aborts, body-read failures — pass through untouched (reified via asFailure so their name and cause chain survive). The only tags fetch raises itself are 'http-status' (from .expect() on a non-ok response) and 'parse' (a response with no body). Cancellation is automatic: fetch forwards the running scope's abort signal, so a halted scope aborts the in-flight request. The underlying implementation is injectable via the fetchImpl context.
Request
Make an HTTP request.
fetch
Perform an HTTP request; returns a chainable operation resolving to a wrapped `Response`.
const fetch: (input: RequestInfo | URL, init?: FetchDef.Init) => FetchDef.OperationThe returned Operation is itself a Future<Response> — yield* it for the response, or call a body shortcut (.json(), .text(), .body(), .stream(), .raw(), …) to fetch and read in one step. Chain .expect() to fail with 'http-status' on any non-ok response. The scope's abort signal is forwarded automatically, so init.signal is intentionally disallowed.
import { fetch } from '@ozaco/std/fetch'
// fetch + decode JSON in one step
const user = yield* fetch('/api/user/42').json<User>()
// POST, then status-check and codec-decode the body
const res = yield* fetch('/api/todos', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: payload,
}).expect()
const created = yield* res.body<Todo>()Context
Inject the underlying fetch implementation.
fetchImpl
Effect context holding the fetch implementation `fetch()` dispatches through.
const fetchImpl: Context<FetchDef.Impl>Defaults to globalThis.fetch. Override it for tests, SSR, or a custom transport with fetchImpl.set(impl) or fetchImpl.with(impl, op) in the running scope; fetch reads it via fetchImpl.get() so the default applies when unset.
import { fetchImpl } from '@ozaco/std/fetch'
yield* fetchImpl.with(mockFetch, function* () {
const data = yield* fetch('/api/thing').json()
// ...
})Types
The `FetchDef` namespace: the response surface, the chainable operation, and configuration shapes.
FetchDef.Response
The wrapped response: standard metadata plus effect-native, codec-aware body readers.
interface Response {
readonly native: globalThis.Response
readonly ok: boolean
readonly status: number
readonly statusText: string
readonly headers: Headers
readonly url: string
readonly redirected: boolean
readonly bodyUsed: boolean
readonly type: ResponseType
json<T = unknown>(): Future<T>
text(): Future<string>
arrayBuffer(): Future<ArrayBuffer>
blob(): Future<Blob>
formData(): Future<FormData>
bytes(): Future<Uint8Array>
body<T = unknown>(): Future<T>
stream<T = unknown>(): Future<Stream<T, StreamClose>>
raw(): Future<Stream<Uint8Array, void>>
expect(): Future<Response>
}body<T>() decodes the whole payload through the registered codec (auto-installs JsonCodec if absent); stream<T>() yields one codec-decoded value per chunk; raw() is the undecoded byte stream; expect() fails with 'http-status' when the response is not ok.
FetchDef.Operation
What `fetch` returns: a `Future<Response>` with the same body readers chained for one-step use.
interface Operation extends Future<Response> {
json<T = unknown>(): Future<T>
text(): Future<string>
arrayBuffer(): Future<ArrayBuffer>
blob(): Future<Blob>
formData(): Future<FormData>
bytes(): Future<Uint8Array>
body<T = unknown>(): Future<T>
stream<T = unknown>(): Future<Stream<T, StreamClose>>
raw(): Future<Stream<Uint8Array, void>>
expect(): Operation
}yield* it for the Response, or call a reader to run the request and read the body together. expect() returns another Operation, so it composes with the readers (e.g. fetch(url).expect().json()).
FetchDef.Init
Request init: a standard `RequestInit` with `signal` removed (the effect scope owns cancellation).
type Init = Omit<RequestInit, 'signal'> & { signal?: never }FetchDef.Impl
The underlying fetch implementation type, injectable via `fetchImpl`.
type Impl = (input: RequestInfo | URL, init?: RequestInit) => Promise<globalThis.Response>FetchDef.Error
Errors surfaced by fetch. Thrown faults pass through as `unknown`; the only tags it raises are `'http-status'` and `'parse'`.
type Error = unknown