Skip to main content

@cuple/client

Functions​

createClient()​

createClient<T>(config): Client<T, { }>

Defined in: packages/client/src/client.ts:3

Type Parameters​

T​

T extends RecursiveApi

Parameters​

config​
path​

string

Returns​

Client<T, { }>


cupleEndpointKey()​

cupleEndpointKey(endpoint): string

Defined in: packages/client/src/cache-key.ts:30

Identifies the route. JSON, not a joined string, because path is a URL.

Parameters​

endpoint​

AnyEndpointRef

Returns​

string


cupleRequestKey()​

cupleRequestKey(endpoint, args): readonly [string, string, unknown]

Defined in: packages/client/src/cache-key.ts:18

Cache key of one call: [endpointKey, clientKey, input].

with({ middleware }) runs per request and what it returns never reaches the key, so a client whose middleware varies needs with({ key }) to keep those responses apart.

options (the RequestInit) is left out. It is transport configuration, not request identity — the server never sees it — and it tends to hold values like an AbortSignal that caches hash by identity, which would make the key change on every render. Two calls differing only in credentials or cache therefore share an entry; give them different with({ key }) if that matters.

Parameters​

endpoint​

AnyEndpointRef

args​

unknown

Returns​

readonly [string, string, unknown]


fetchCuple()​

fetchCuple<TEndpoint>(endpoint, ...args): CuplePromise<TEndpoint["tOutput"]>

Defined in: packages/client/src/client.ts:310

Sends one request. Like fetch, it resolves with whatever the server answered — success, a 404, an invalid-body — typed as the route's results, and rejects only when there was no answer:

OutcomeRejects with
No response: unreachable, DNS, CORSCupleTransportError
Body is not JSON: proxy HTML, gateway pageCupleTransportError (statusCode)
options.signal abortedDOMException (name: "AbortError")

Narrow it on the promise: .thenKeepSuccess() for just the data, .thenReject(["unexpected-error"]) to send results nobody handles where unhandled errors go. Rejected results throw CupleUnexpectedResponseError. See CuplePromise. The HTTP status is never interpreted: it is copied onto the result as statusCode, and which result goes with which status is the server's choice, set by apiResponse.

A non-JSON body is always an error here — fetchCuple only speaks Cuple's envelope. For downloads, streams and any other custom response, define the route with getRaw/postRaw/… on the server and call it with plain fetch; raw routes are not part of the client API. (Raw request bodies are fine: pass an ArrayBuffer, Blob, Uint8Array or ReadableStream as body.)

Type Parameters​

TEndpoint​

TEndpoint extends ClientEndpointRef

Parameters​

endpoint​

TEndpoint

args​

...FetchCupleArgs<TEndpoint>

Returns​

CuplePromise<TEndpoint["tOutput"]>


fetchCupleSSE()​

fetchCupleSSE<TEndpoint>(endpoint, ...args): CuplePromise<TEndpoint["tOutput"]>

Defined in: packages/client/src/client.ts:405

Type Parameters​

TEndpoint​

TEndpoint extends ClientSSEEndpointRef

Parameters​

endpoint​

TEndpoint

args​

...FetchCupleSSEArgs<TEndpoint>

Returns​

CuplePromise<TEndpoint["tOutput"]>


transportErrorResult()​

transportErrorResult(error): TransportErrorResult

Defined in: packages/client/src/client.ts:61

Parameters​

error​

CupleTransportError

Returns​

TransportErrorResult

Classes​

CuplePromise​

Defined in: packages/client/src/client.ts:115

A request's result. Like fetch, it resolves with every response the server sent, and rejects when there was none: a network failure as CupleTransportError, an abort as AbortError. Narrow it with:

MethodResolves with
(default)every result the server sent
.thenKeepSuccess()success
.thenKeep([...])exactly the listed results; "success" isn't implied
.thenKeepAlso([...])what it resolved with so far, plus the listed results
.thenReject([...])every result the server sent, except the listed ones
.thenRejectAlso([...])what it resolved with so far, minus the listed results
.thenKeepAll()every result, plus transport-error and abort

Results it doesn't keep reject as CupleUnexpectedResponseError. List "transport-error" or "abort" to keep them as values.

Each method starts from the response again, so they chain in any order.

Extends​

  • Promise<TValue>

Type Parameters​

TAll​

TAll extends object

TValue​

TValue = TAll

Accessors​

[species]​
Get Signature​

get static [species](): PromiseConstructor

Defined in: packages/client/src/client.ts:121

Returns​

PromiseConstructor

Overrides​

Promise.[species]

Constructors​

Constructor​

new CuplePromise<TAll, TValue>(executor): CuplePromise<TAll>

Defined in: docs/node_modules/typescript/lib/lib.es2015.promise.d.ts:31

Creates a new Promise.

Parameters​
executor​

(resolve, reject) => void

A callback used to initialize the promise. This callback is passed two arguments: a resolve callback used to resolve the promise with a value or the result of another promise, and a reject callback used to reject the promise with a provided reason or error.

Returns​

CuplePromise<TAll>

Inherited from​

Promise<TValue>.constructor

Methods​

thenKeep()​

thenKeep<TResult>(results): CuplePromise<TAll, Listed<TAll, TResult>>

Defined in: packages/client/src/client.ts:185

Resolve with exactly the listed results. The list is complete: thenKeep(["order-not-found"]) rejects a success too.

"transport-error" and "abort" can be listed too: a network failure then resolves as { result: "transport-error", statusCode, message }, an abort as { result: "abort", statusCode: null, message }.

Type Parameters​
TResult​

TResult extends string

Parameters​
results​

readonly TResult[]

Returns​

CuplePromise<TAll, Listed<TAll, TResult>>

thenKeepAll()​

thenKeepAll(): CuplePromise<TAll, TransportErrorResult | AbortResult | TAll>

Defined in: packages/client/src/client.ts:241

Resolve with everything: every result the server sent, plus transport-error and abort. Only a bug in your own code rejects.

Returns​

CuplePromise<TAll, TransportErrorResult | AbortResult | TAll>

thenKeepAlso()​

thenKeepAlso<TResult>(results): CuplePromise<TAll, TValue | Listed<TAll, TResult>>

Defined in: packages/client/src/client.ts:201

Also resolve with the listed results: thenKeepSuccess().thenKeepAlso(["invalid-body"]) resolves with success | invalid-body. Mostly for "transport-error" and "abort", which reject unless listed.

Type Parameters​
TResult​

TResult extends string

Parameters​
results​

readonly TResult[]

Returns​

CuplePromise<TAll, TValue | Listed<TAll, TResult>>

thenKeepSuccess()​

thenKeepSuccess(): CuplePromise<TAll, Extract<TAll, { result: "success"; }>>

Defined in: packages/client/src/client.ts:169

Resolve with success only; anything else rejects. For code that wants the data: const { post } = await fetchCuple(...).thenKeepSuccess().

Returns​

CuplePromise<TAll, Extract<TAll, { result: "success"; }>>

thenReject()​

thenReject<TResult>(results): CuplePromise<TAll, Exclude<TAll, { result: TResult; }>>

Defined in: packages/client/src/client.ts:216

Resolve with every result the server sent, except the listed ones, which reject: thenReject(["unexpected-error"]) sends a 500 where unhandled errors go. A network failure or an abort still rejects.

Type Parameters​
TResult​

TResult extends string

Parameters​
results​

readonly TResult[]

Returns​

CuplePromise<TAll, Exclude<TAll, { result: TResult; }>>

thenRejectAlso()​

thenRejectAlso<TResult>(results): CuplePromise<TAll, Exclude<TValue, { result: TResult; }>>

Defined in: packages/client/src/client.ts:227

Also reject the listed results: what it resolved with so far, minus these.

Type Parameters​
TResult​

TResult extends string

Parameters​
results​

readonly TResult[]

Returns​

CuplePromise<TAll, Exclude<TValue, { result: TResult; }>>

of()​

static of<TAll, TValue>(response, keep?): CuplePromise<TAll, TValue>

Defined in: packages/client/src/client.ts:129

response is everything the server answered; keep says what resolves.

Type Parameters​
TAll​

TAll extends object

TValue​

TValue = TAll

Parameters​
response​

Promise<TAll>

keep?​

Keep = ...

Returns​

CuplePromise<TAll, TValue>


CupleTransportError​

Defined in: packages/client/src/client.ts:35

The server did not answer in Cuple's format: it was unreachable (DNS, CORS, offline), or it answered with a body that is not JSON (a proxy's HTML error page). The original error is kept as cause.

A bug in your own code never produces this, so it is safe to treat as "retry later" rather than "report".

Extends​

  • Error

Constructors​

Constructor​

new CupleTransportError(message, options): CupleTransportError

Defined in: packages/client/src/client.ts:42

Parameters​
message​

string

options​
cause​

unknown

statusCode?​

number | null

Returns​

CupleTransportError

Overrides​

Error.constructor

Properties​

cause​

readonly cause: unknown

Defined in: packages/client/src/client.ts:38

What failed underneath: fetch's TypeError, or the JSON SyntaxError.

Overrides​

Error.cause

name​

name: string = "CupleTransportError"

Defined in: packages/client/src/client.ts:36

Overrides​

Error.name

statusCode​

readonly statusCode: number | null

Defined in: packages/client/src/client.ts:40

The HTTP status, when a response arrived but its body was not JSON.


CupleUnexpectedResponseError​

Defined in: packages/client/src/client.ts:17

Extends​

  • Error

Constructors​

Constructor​

new CupleUnexpectedResponseError(response?): CupleUnexpectedResponseError

Defined in: packages/client/src/client.ts:19

Parameters​
response?​
message?​

string

result?​

string

statusCode?​

number

Returns​

CupleUnexpectedResponseError

Overrides​

Error.constructor

Properties​

response?​

optional response?: object

Defined in: packages/client/src/client.ts:20

message?​

optional message?: string

result?​

optional result?: string

statusCode?​

optional statusCode?: number

statusCode​

statusCode: number | null

Defined in: packages/client/src/client.ts:18

Type Aliases​

AbortResult​

AbortResult = object

Defined in: packages/client/src/client.ts:70

An aborted request, as a result: list "abort" in thenKeepAlso/thenKeep.

Properties​

message​

message: string

Defined in: packages/client/src/client.ts:70

result​

result: "abort"

Defined in: packages/client/src/client.ts:70

statusCode​

statusCode: null

Defined in: packages/client/src/client.ts:70


Client​

Client<TApi, TPreloadedData> = MapApi<TApi, TPreloadedData> & NonNullable<unknown> extends TPreloadedData ? object : NonNullable<unknown>

Defined in: packages/client/src/client.ts:550

Type Parameters​

TApi​

TApi extends RecursiveApi

TPreloadedData​

TPreloadedData = NonNullable<unknown>


ClientEndpointRef​

ClientEndpointRef = object

Defined in: packages/client/src/client.ts:258

Properties​

_sse?​

optional _sse?: never

Defined in: packages/client/src/client.ts:262

clientProps​

clientProps: ClientProps

Defined in: packages/client/src/client.ts:263

tInput​

tInput: Record<string, unknown>

Defined in: packages/client/src/client.ts:259

tMethod​

tMethod: any

Defined in: packages/client/src/client.ts:261

tOutput​

tOutput: any

Defined in: packages/client/src/client.ts:260


ClientProps​

ClientProps = object

Defined in: packages/client/src/map-api.ts:26

Properties​

finalware?​

optional finalware?: (response) => unknown | Promise<unknown>

Defined in: packages/client/src/map-api.ts:46

Runs after every response, set by client.with({ finalware }). Its return value replaces the response; the declared types do not follow it.

Parameters​
response​

any

Returns​

unknown | Promise<unknown>

key?​

optional key?: string | (() => string)

Defined in: packages/client/src/map-api.ts:41

Identifies what middleware injects, set by client.with({ key }). Cache integrations put it in the cache key, so responses that differ only by injected data are never mixed up. Either a string or a synchronous getter — the key has to be buildable during render, before any request runs.

method​

method: any

Defined in: packages/client/src/map-api.ts:27

middleware?​

optional middleware?: () => any

Defined in: packages/client/src/map-api.ts:34

Runs before every request, set by client.with({ middleware }). What it returns is merged into the request data.

Returns​

any

path​

path: any

Defined in: packages/client/src/map-api.ts:29

segments​

segments: any

Defined in: packages/client/src/map-api.ts:28


ClientSSEEndpointRef​

ClientSSEEndpointRef = object

Defined in: packages/client/src/client.ts:392

Properties​

_sse​

_sse: true

Defined in: packages/client/src/client.ts:396

clientProps​

clientProps: ClientProps

Defined in: packages/client/src/client.ts:397

tInput​

tInput: Record<string, unknown>

Defined in: packages/client/src/client.ts:393

tMethod​

tMethod: any

Defined in: packages/client/src/client.ts:395

tOutput​

tOutput: any

Defined in: packages/client/src/client.ts:394


CupleResult​

CupleResult<TEndpoint> = TEndpoint["tOutput"]

Defined in: packages/client/src/client.ts:267

Everything an endpoint can resolve to.

Type Parameters​

TEndpoint​

TEndpoint extends ClientEndpointRef


CupleResultOf​

CupleResultOf<TEndpoint, TResult> = Extract<CupleResult<TEndpoint>, { result: TResult; }>

Defined in: packages/client/src/client.ts:276

One named case, e.g. CupleResultOf<typeof e, "notFound">.

Type Parameters​

TEndpoint​

TEndpoint extends ClientEndpointRef

TResult​

TResult extends string


CupleSuccess​

CupleSuccess<TEndpoint> = Extract<CupleResult<TEndpoint>, { result: "success"; }>

Defined in: packages/client/src/client.ts:270

Just the successful case: what thenKeepSuccess() resolves with.

Type Parameters​

TEndpoint​

TEndpoint extends ClientEndpointRef


CupleWithOptions​

CupleWithOptions<TParams> = object

Defined in: packages/client/src/client.ts:506

Options for client.with(..).

The two fields are deliberately separate concerns: data is about the request, key is about the cache. A cookie-authenticated app needs only key; a static API-key client needs only data.

Type Parameters​

TParams​

TParams

Properties​

finalware?​

optional finalware?: (response) => unknown | Promise<unknown>

Defined in: packages/client/src/client.ts:547

Runs after every response this client receives, before it is handed back.

For the cross-cutting work that has to happen whether or not a hook is involved: redirecting on an expired session, reporting failures. Throwing from here turns a result into an exception, which is how a redirect works.

Returning a value replaces the response; returning nothing keeps it.

The types do not follow it. A replaced response still has the endpoint's declared type, because the response type is fixed by the route definition and there is no way to thread a per-client transformation back through it. Reshaping data here will lie to every caller — observe, throw, or narrow by hand at the call site.

Parameters​
response​

any

Returns​

unknown | Promise<unknown>

key?​

optional key?: string | (() => string)

Defined in: packages/client/src/client.ts:531

Identifies what middleware injects, for cache integrations.

middleware runs per request, so nothing it returns reaches the cache key: two calls that differ only in what it injected would share one entry. This is how a cache tells them apart. Most often that is who the request is for, but it is whatever the middleware actually varies by — a tenant, a locale, an API version.

Key what the response depends on, not the injected bytes. A refreshed token is new data but the same identity; a key that moved with it would discard the cache on every refresh and orphan pending invalidations.

A getter must be synchronous, since the key is built during render. It is read on each render, so whatever it reads has to live somewhere that re-renders the tree — otherwise pass a plain string and build one client per value.

middleware?​

optional middleware?: () => Promise<TParams> | TParams

Defined in: packages/client/src/client.ts:512

Runs before every request this client sends; what it returns is merged into the request data, under the per-call options. Awaited at fetch time, so it can refresh a token.

Returns​

Promise<TParams> | TParams


FetchCupleArgs​

FetchCupleArgs<TEndpoint> = object extends TEndpoint["tInput"] ? [Merge<TEndpoint["tInput"], GenericOptions>] : [Merge<TEndpoint["tInput"], GenericOptions>]

Defined in: packages/client/src/client.ts:281

Type Parameters​

TEndpoint​

TEndpoint extends ClientEndpointRef


FetchCupleSSEArgs​

FetchCupleSSEArgs<TEndpoint> = object extends TEndpoint["tInput"] ? [Merge<TEndpoint["tInput"], GenericOptions>] : [Merge<TEndpoint["tInput"], GenericOptions>]

Defined in: packages/client/src/client.ts:400

Type Parameters​

TEndpoint​

TEndpoint extends ClientSSEEndpointRef


MapApi​

MapApi<TApi, TPreloadedData> = { [Key in keyof TApi]: TApi[Key] extends { tInput: infer TInput; tMethod: infer TMethod extends string } ? AlterEndpoint<TApi[Key], TInput, TMethod, TPreloadedData> : MapApi<TApi[Key], TPreloadedData> }

Defined in: packages/client/src/map-api.ts:2

Exclude data set with .with() for the whole API

Type Parameters​

TApi​

TApi

TPreloadedData​

TPreloadedData


RecursiveApi​

RecursiveApi = { [Key in string]: { _handler: (req: any, res: any) => void; _method: any; tInput: any; tMethod: any; tOutput: any } | RecursiveApi }

Defined in: packages/client/src/client.ts:487


TransportErrorResult​

TransportErrorResult = object

Defined in: packages/client/src/client.ts:55

A network failure as a result, for code that handles it as a value: list "transport-error" in thenKeepAlso/thenKeep (or resolveAlso on a read). statusCode is set when a response arrived but wasn't Cuple's (a proxy's error page); null when there was no response at all.

Properties​

message​

message: string

Defined in: packages/client/src/client.ts:58

result​

result: "transport-error"

Defined in: packages/client/src/client.ts:56

statusCode​

statusCode: number | null

Defined in: packages/client/src/client.ts:57