# Types

Complete reference for all TypeScript types exported by @noverax/courier.

## Overview

All TypeScript types used across the Courier library, organized by category.

## Client Types

### TypedClient

The main typed client returned by `createCaller` and `createProxyCaller`. Provides dot-notation access to groups, `.raw` for full response, and `.with()` for per-request options.

```ts
type TypedClient<T extends DefinedApi<any>, Raw extends boolean = false> = {
  [K in keyof ApiGroups<T>]: GroupClient<ApiGroups<T>[K], Raw>
} & {
  raw: TypedClient<T, true>
  with(options: WithOptions): TypedClient<T, Raw>
}
```

### GroupClient

A group with typed endpoint methods, `.raw` accessor, and `.with()`: one method per endpoint of the group, typed from its variables and response, beside these two.

```ts
type GroupClient<G, Raw extends boolean = false> = {
  // …one method per endpoint of G…
  raw: GroupClient<G, true>
  with(options: WithOptions): GroupClient<G, Raw>
}
```

### WithOptions

Options for `.with()` — all `CallOptions` except `rawData` (controlled via `.raw`).

```ts
type WithOptions = Omit<CallOptions, "rawData">
```

### CallerDefaults

Options for `createCaller`.

```ts
type CallerDefaults = {
  timeout?: number
  headers?: Record<string, string>
  context?: Context
  onError?: (error: HTTPError) => void | Promise<void>
  onSuccess?: (data: unknown) => void | Promise<void>
}
```

### ProxyCallerOptions

Options for `createProxyCaller` and `createProxyQueryCaller`, which take them after the routes of an API.

```ts
type ProxyPath = {
  http?: string  // default: "/api/request"
  sse?: string   // default: "/api/sse"
  ws?: string    // no default — throws if WS endpoint invoked without it
}

type ProxyCallerOptions = {
  proxyPath?: ProxyPath
  timeout?: number
  cancelPrevious?: readonly string[]
  coalesce?: boolean
  credentials?: RequestCredentials
  headers?: Record<string, string>
  onError?: (error: HTTPError) => void | Promise<void>
  onSuccess?: (data: unknown) => void | Promise<void>
  ws?: CallerWSOptions
}
```

### CourierRoutes

The routes of one API that a page's proxy client takes: the source the server registered it as, and each endpoint a page may call, by its path, with how the page reaches it. Courier writes them into `courier.routes.ts` from the endpoints marked `.expose()` — see [Exposing Endpoints](/docs/proxy-mode/expose).

```ts
import type { CourierRoutes, RouteMap, RouteShape } from "@noverax/courier/define"

// RouteShape: { type: "query"; get?: true } | { type: "mutation" }
//           | { transport: "sse" } | { transport: "ws"; bidirectional?: true }
// RouteMap<TApi>: the paths of TApi, each in the shape the API declares it
// CourierRoutes<TApi, TEndpoints>: { source, endpoints, cancelPrevious?, coalesce? }
```

## Endpoint Definition Types

### Endpoint Types

An endpoint is an inert descriptor, not a callable. One of three types names it,
according to the head it was built from:

```ts
import type {
  AnyEndpoint,      // any of the three, when the kind does not matter
  ChannelEndpoint,  // ChannelEndpoint<Response, Variables, Send>
  HttpEndpoint,     // HttpEndpoint<Response, Variables, Kind extends "query" | "mutation">
  StreamEndpoint,   // StreamEndpoint<Response, Variables>
} from "@noverax/courier/define"
```

### Inference Helpers

Read the types back off an endpoint. This is how a caller knows what a method
takes and returns:

```ts
import type { InferClient } from "@noverax/courier" // InferClient<TApi>: the client createCaller(api) returns
import type {
  InferKind,          // InferKind<E>: "query" | "mutation" | "stream" | "channel"
  InferResponse,      // InferResponse<E>: what the endpoint resolves to
  InferSend,          // InferSend<E>: what a channel accepts from the client
  InferVariables,     // InferVariables<E>: what the caller must pass
  InferVariablesOut,  // InferVariablesOut<E>: what its closure receives, once a schema has validated the call
} from "@noverax/courier/define"
```

The clients infer all of this themselves; name a type with these helpers where one is needed elsewhere — a component's props, a test's fixture.

### Wire Surfaces

The object `.via()` hands the closure. Name these to lift a closure out of the
chain into a function of its own:

```ts
interface HttpWire {
  get(path?: string, variables?: unknown): WireCall
  post(path?: string, body?: unknown): WireCall
  put(path?: string, body?: unknown): WireCall
  patch(path?: string, body?: unknown): WireCall
  del(path?: string, variables?: unknown): WireCall
  head(path?: string, variables?: unknown): WireCall
}

interface StreamWire {
  get(path?: string, variables?: unknown): WireCall
}

interface ChannelWire {
  connect(path?: string, variables?: unknown): WireCall
}

type HttpProbe<Variables> = (http: HttpWire, variables: Variables) => WireCall
type StreamProbe<Variables> = (sse: StreamWire, variables: Variables) => WireCall
type ChannelProbe<Variables> = (ws: ChannelWire, variables: Variables) => WireCall
```

```ts
import type { HttpProbe } from "@noverax/courier/define"

const byId: HttpProbe<{ id: string }> = (http, vars) => http.get(":id", vars)

const getById = endpoint.variables<{ id: string }>().via(byId).response<User>()
```

## Response Types

### HttpResponse

```ts
type HttpResponse<T = unknown> = {
  status: number    // HTTP status code
  headers: Headers  // Response headers
  data: T           // Parsed response body
}
```

## Options Types

### CallOptions

Per-request options passed when calling an endpoint.

```ts
type CallOptions<R extends boolean = false> = Omit<RequestInit, "method" | "body"> & {
  timeout?: number
  responseType?: "json" | "text" | "blob" | "arrayBuffer" | "formData"
  onDownloadProgress?: (progress: { percent: number; transferredBytes: number; totalBytes: number }) => void
  onUploadProgress?: (progress: UploadProgress) => void
  rawData?: R
  forwardVariables?: boolean
  stream?: boolean
  method?: "GET" | "POST"
}
```

`headers`, `signal`, `credentials` and the rest of `RequestInit` are passed to `fetch`; `method` is the verb a call goes to the proxy with, not the endpoint's own.

### UploadProgress

```ts
type UploadProgress = {
  percent: number           // 0 to 1
  transferredBytes: number
  totalBytes: number
}
```

### MethodParameters

```ts
type MethodParameters<T extends HttpMethod> = T extends "head"
  ? [url?: string, options?: MethodOptions<T>]
  : [url?: string, variables?: Record<string, unknown>, options?: MethodOptions<T>]
```

## Source & Config Types

### BaseOptions

Core configuration for `defineApi()`.

```ts
type BaseOptions = MergeOptions & FetchOptions & {
  baseURL?: string
  responseType?: ResponseType
  responseParser?: (response: Response) => Promise<unknown>
  defaultBody?: Record<string, unknown>
  defaultQueryParams?: Record<string, unknown>
  allowedHeaders?: string[]
  bodySerializer?: (data: Record<string, unknown>) => BodyInit
  searchParamsSerializer?: SearchParamsSerializer
  cancelPrevious?: readonly string[]
  middleware?: Middleware[]
  expose?: boolean
  proxyPath?: ProxyPath
}
```

### GroupOptions

```ts
type GroupOptions = MergeOptions & {
  prefix?: string
}
```

### ResponseType

```ts
type ResponseType = "json" | "text" | "blob" | "arrayBuffer" | "formData"
```

### SearchParamsSerializer

```ts
type SearchParamsSerializer = {
  stringify: (obj: Record<string, unknown>) => string
  parse: (str: string) => Record<string, unknown>
}
```

### Context

```ts
type Context = {
  req?: Request
  res?: Response
  headers?: Headers
  proxyMethod?: "GET" | "POST"
}
```

### PathOptions

```ts
type PathOptions = (request?: Request) =>
  Record<string, boolean | number | string | null | undefined> | undefined
  | Promise<Record<string, boolean | number | string | null | undefined> | undefined>
```

## Middleware Types

### Middleware

```ts
type Middleware =
  | { name: string; phase: "before"; handler: BeforeHandler }
  | { name: string; phase: "after"; handler: AfterHandler }
  | { name: string; phase: "wrap"; handler: WrapHandler }
```

`defineMiddleware(name, phase, handler)` builds one — see [Middleware](/docs/middleware/overview).

### MiddlewareContext

```ts
type MiddlewareContext = {
  source: string
  group?: string
  method: string
  variables?: unknown
  headers: Headers
  transport?: "http" | "sse" | "ws"
  request?: Request
  kind?: "query" | "mutation"
  carriesSession?: boolean
  sessionPartition?: string
  signal?: AbortSignal
  purpose?: CallPurpose
}

type CallPurpose = "csrf-token"
```

`purpose` is set on a request the session makes rather than an endpoint's call — `"csrf-token"` for the double-submit token a write asks for — whose `method` names no endpoint. See [Middleware](/docs/middleware/overview) for each field.

### MiddlewareResponse

```ts
type MiddlewareResponse = {
  status: number
  data: unknown
  headers: Headers
}
```

### NextFn

```ts
type NextFn = () => Promise<MiddlewareResponse>
```

## React Query Types

```ts
type QueryOptions<R, V> = WithVariables<V> &
  Omit<UseQueryOptions<R, Error, R, QueryKey>, "queryKey" | "queryFn"> & {
    requestOptions?: CallOptions
  }

type MutationOptions<R, V> = Omit<
  UseMutationOptions<R, Error, MutationVariables<V>>,
  "mutationFn"
> & {
  requestOptions?: CallOptions
}

type MutationVariables<V> = [V] extends [undefined]
  ? void
  : {} extends V ? void | V : V

type WithVariables<V> = [V] extends [undefined]
  ? { variables?: undefined }
  : {} extends V
    ? { variables?: V }
    : { variables: V }
```

## Related

- [Type Safety Guide](/docs/core-concepts/type-safety) — how type inference works
- [createProxyCaller](/docs/api/create-proxy-caller) — uses TypedClient, CourierRoutes and ProxyCallerOptions
- [defineApi](/docs/api/define) — uses BaseOptions
- [HttpClient](/docs/api/instance) — the runtime that carries out a wire call
