StatsHub Docs
Packages

api-client

The platform-neutral JSON transport shared by web and Expo.

statshub-api-client owns HTTP behavior that must agree across the browser, Next.js, and React Native. It has no React, Next.js, Expo, Supabase, or Better Auth dependency.

Exports

ExportTypeDescription
createHttpClientfunctionCreates a client with get, post, put, patch, delete, and request methods.
buildUrlfunctionJoins a base URL and path, drops nullish query values, and serializes arrays as comma-separated values.
readResponseBodyfunctionReads empty, JSON, plain-text, and HTML bodies without losing the original text.
ApiErrorclassCarries the HTTP status, URL, and parsed body. Status 0 means no response arrived.
isAbortErrorfunctionRecognises browser cancellation and React Native's released-response cancellation error.

HttpClientConfig

PropertyTypeRequiredDefaultDescription
baseUrlstringNosame-origin pathPrefix for every request path.
fetch(url, init) => Promise<Response>Noglobal fetchAdapter used by Next.js to add cache metadata and by tests to supply responses.
headersHeadersInitNononeHeaders applied to every request.
getHeaders() => HeadersInit | Promise<HeadersInit>NononeRequest-scoped cookie or bearer headers. Called for every request.
unwrapDatabooleanNofalseReturns the value inside a successful { data: value } body.

Header precedence is fixed: static client headers, then getHeaders, then the JSON content type, then request headers. A caller can override any earlier value for one request.

Request behavior

ConditionResult
undefined or null query valueOmitted from the URL.
Array query valueOne comma-separated query value.
Body is presentJSON encoded with Content-Type: application/json.
Empty successful bodyResolves as undefined.
Non-2xx responseThrows ApiError with the parsed body.
Network failureThrows ApiError with status 0.
Aborted requestPreserves AbortError; never reports it as a network failure.

Example

import { createHttpClient } from "statshub-api-client";

const api = createHttpClient({
  baseUrl: "https://www.statshub.com/api",
});

const fixtures = await api.get<{ data: unknown[] }>("/event/by-date", {
  query: { startOfDay: 1787950800, endOfDay: 1788037200 },
});

Platform adapters

ConsumerAdapter responsibility
Web Server ComponentsAdds Next.js revalidation tags. Private reads inject the complete Supabase cookie header and use no-store.
Web client componentsGives SWR a same-origin get or post function.
ExpoSupplies the absolute API origin. The StatsHub-specific client keeps its Cloudflare backoff and cached-5xx retry.

getHeaders is an authentication seam, not an identity provider. Both apps sign in against the same Supabase project, and the Go API validates that identity in either shape — web sends the @supabase/ssr cookie, Expo sends the access token as a bearer header. Sharing the interface is not what makes them compatible; sharing the project is.

Errors

ErrorCondition
ApiError with status 0Fetch failed before an HTTP response arrived.
ApiError with status 400599The server returned a non-success status.
AbortErrorThe caller cancelled the request.
  • Web data — Next.js cache and SWR adapters.
  • Expo data — React Query resources and API-specific retries.
  • API contract — response compatibility between API implementations.

On this page