Skip to content
Client logo

Client

Officialv6.0.4

@kubb/plugin-client

kubb add plugin-client

Stream Server-Sent Events and JSON Lines

Add client.stream and its types to your client module, so streamed operations compile and yield typed events or lines.

Add a stream method

When the spec has a Server-Sent Events or JSON Lines operation, its generated function calls client.stream instead of client:

import type { Options, StreamResult, SuccessOf, TypedEvent } from '../../../client'
import type { StreamChatOptions, StreamChatResponses } from '../../types/StreamChat'
import { client } from '../../../client'

export function streamChat<ThrowOnError extends boolean = true>(
  options: Options<StreamChatOptions, ThrowOnError> = {},
): Promise<StreamResult<StreamChatResponses, ThrowOnError, TypedEvent<SuccessOf<StreamChatResponses>>>> {
  const { client: apiClient = client, ...config } = options

  return apiClient.stream<StreamChatResponses, ThrowOnError, TypedEvent<SuccessOf<StreamChatResponses>>>({
    method: 'POST',
    url: '/chat',
    contentType: { response: 'text/event-stream' },
    eventShape: 'event',
    rawData: true,
    ...config,
    throwOnError: config.throwOnError ?? true,
  })
}
CallMust return
client<TResponses, ThrowOnError>(config)Promise<RequestResult<TResponses, ThrowOnError>>
client.stream<TResponses, ThrowOnError, TItem>(config)Promise<StreamResult<TResponses, ThrowOnError, TItem>>

Export the stream types

Your module needs these on top of the contract:

ExportKindNeeded when
client.stream, StreamResultmethod, typeThe spec has Server-Sent Events or JSON Lines operations.
StreamResultWithHeaderstypeA stream declares response headers. It replaces StreamResult. With returnType: 'data', UnwrappedStreamResultWithHeaders replaces UnwrappedStreamResult. A stream that types only the payload also imports SuccessOf and ServerSentEvent.
SuccessOf, TypedEventtypeA stream names each event (both) or streams JSON Lines (SuccessOf).

Type each item

The third type argument, TItem, follows the document:

The documentTItem
Names each eventTypedEvent<SuccessOf<TResponses>>
Streams JSON LinesSuccessOf<TResponses>
Types only the payloadLeft out. Give TItem a default, such as ServerSentEvent<SuccessOf<TResponses>>.

Read the stream fields

Declare these fields on RequestConfig. The call passes them next to the usual fields:

FieldPassed whenValue
contentTypeThe operation has a body, streams, or offers text/event-streamrequest is the body's media type, response the one to ask for in Accept.
eventShapeA Server-Sent Events operation'event' or 'data': what validator.response checks on each event.
rawDataA Server-Sent Events operation types data as a stringtrue, or the names of those events. Keep their data as text.

Parse JSON Lines

A JSON Lines call, such as application/jsonl or application/x-ndjson, passes the media type in contentType.response and expects one parsed item per line.

The shared runtime's sse.ts exports both parsers: parseEventStream reads events and applies rawData, and parseJsonLines reads one item per line.

Streams with full or data return types

With returnType 'full' or 'data', every operation imports helpers from your module, and streams import more types:

returnTypeExtra exportsStream operations also import
'full'withUnwrap, resolveThrowOnError, UnwrappableStreamOptions, StreamResult
'data'unwrapResult, resolveThrowOnError, UnwrappedResultStreamOptions, UnwrappedStreamResult

'full' and 'data' need a StreamResult with data and error, so the minimal type in Add a stream method is not enough. @kubb/plugin-client/templates/core.ts exports all of these.

Next, build the client on the shared runtime, which ships client.stream.