Server Fetch
Cookie-aware fetch for RSC & actions
serverFetch is a small, typed HTTP client for the places the React hook can't run: server components, server actions and route handlers. It speaks the same conventions as the generated client — normalised responses, timeouts and retries — without any React lifecycle.
Where useApiActions wraps interactive, stateful calls, serverFetch is for fetch-on-the-server-then-render: load data during SSR, mutate inside a server action, then revalidate. It returns a rich ServerFetchResponse including the raw Set-Cookie headers, so refreshed auth cookies can be forwarded straight back to the browser.
Use the shared serverFetch singleton for quick calls, or construct a ServerFetch with its own base URL and defaults for a specific upstream.
Making a request#
Each call describes the url and method, with optional headers, body, and per-request timeout/retry overrides. Object bodies are JSON-encoded for you. The generic parameters type both the success payload (T) and the error shape (E), where E defaults to the exported BaseError type — { message: string; code?: string; details?: unknown }.
1import { cookies } from "next/headers";2import { serverFetch } from "nucleus-core-ts";3import type { Product } from "@/types";4 5const cookie = (await cookies()).toString();6const res = await serverFetch.fetch<Product[]>({7 url: `${process.env.API_BASE_URL}/products`,8 method: "GET",9 headers: { cookie },10});11 12if (res.isSuccess) renderProducts(res.response);serverFetch.fetch<T, E>(options)(options) => Promise<ServerFetchResponse<T, E>>OptionalserverFetch is a shared ServerFetch instance; call serverFetch.fetch(options) to perform a request and resolve to a typed, normalised response. Never throws on HTTP errors — inspect isSuccess and code instead.
verb shortcutsget/delete(url, options?) · post/put/patch(url, body, options?)OptionalThe instance also exposes verb helpers that delegate to fetch(): serverFetch.get(url, options?), serverFetch.delete(url, options?), and serverFetch.post/put/patch(url, body, options?) — each returns the same ServerFetchResponse<T, E>.
options.urlstringRequiredAbsolute URL, or a path appended to the instance baseUrl when one is configured.
options.method'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'RequiredThe HTTP verb for the request.
options.bodyBodyInit | Record<string, unknown>OptionalRequest body. Plain objects are serialised to JSON with the right Content-Type; pass a BodyInit (FormData, string…) to take control.
options.headersHeadersInitOptionalPer-request headers, merged over the instance defaultHeaders. This is where you forward the incoming request's cookie header for authenticated SSR calls.
options.timeoutnumberOptionalPer-request timeout in ms, overriding the instance default.
options.retries / options.retryDelaynumberOptionalOverride how many times (and how long between, in ms) the request is retried for this call. Retries apply only to connection or timeout errors — a completed non-2xx HTTP response is returned immediately and never retried.
Configuring an instance#
new ServerFetch(config) creates a client preset with a base URL, default headers and global timeout/retry policy — handy when one service has its own conventions. The exported serverFetch is just a ready-made default instance.
baseUrlstringOptionalPrefix prepended to relative request URLs.
defaultHeadersRecord<string, string>OptionalHeaders sent on every request from this instance (e.g. an API version or service token).
timeoutnumberOptionalDefault timeout in ms applied when a call doesn't override it.
30000retries / retryDelaynumberOptionalDefault retry count and delay (ms) across this instance, for transient network/timeout failures only — non-2xx HTTP responses are returned, not retried. Defaults to no retries, 1000 ms apart when enabled.
0 / 1000debugbooleanOptionalEnable pretty-printed, colorized log output for this instance. It only changes formatting: requests are logged (with timing and request id) on every call regardless, since the internal Logger runs at 'info' level independent of this flag.
falseThe response shape#
ServerFetchResponse is deliberately explicit — no exceptions to catch. It tells you whether it worked, the parsed body or errors, the status, and crucially the raw Set-Cookie headers so token rotation can be relayed to the client.
isSuccessbooleanOptionalWhether the upstream returned a 2xx. Branch on this, not on try/catch.
response / errorsT | E | undefinedOptionalThe parsed success payload, or the parsed error body when isSuccess is false. E defaults to the exported BaseError type ({ message, code?, details? }); when the request never completes (transport/timeout error) or the error body is non-JSON or empty, the client synthesises a plain { message } object as E rather than parsing one.
codenumber | nullOptionalThe HTTP status code, or null if the request never completed.
rawSetCookiesstring[]OptionalRaw Set-Cookie headers from the upstream — forward these to the browser to propagate refreshed access/refresh tokens.
headers / durationMs / requestId / createdAtmetadataOptionalResponse headers, wall-clock duration, a correlation id and a timestamp for logging and tracing.
Related sections