Skip to content

Stream

You can return a continuous application stream with ResponseContract.stream for binary chunks, or ResponseContract.streamText for text chunks.

ts
import { ResponseContract, 
useRouteBuilder
} from "@duplojs/http";
import {
DPE
,
sleep
} from "@duplojs/utils";
useRouteBuilder
("GET", "/binary-stream")
.
handler
(
ResponseContract.
stream
(
"binary-stream",
DPE
.
number
(),
), (
__
, {
streamResponse
}) =>
streamResponse
(
"binary-stream", async({
send
}) => {
await
send
(12);
await
sleep
(500);
await
send
(20);
}, ), );
useRouteBuilder
("POST", "/text-stream")
.
extract
({
body
: {
value
:
DPE
.
string
(),
}, }) .
handler
(
ResponseContract.
streamText
("text-stream"),
({
value
}, {
streamTextResponse
}) =>
streamTextResponse
(
"text-stream", async({
send
}) => {
await
send
("hello");
await
sleep
(500);
await
send
(` ${
value
}`);
}, ), );

stream is suited for opaque chunks on the client side. streamText is more convenient when you want to consume strings directly.

Consume the stream on the client

The client detects this response type automatically and returns an iterable object enriched with onStream hooks.

ts
import { 
createHttpClient
} from "@duplojs/http/client";
import { type
Routes
} from "./types";
const
client
=
createHttpClient
<
Routes
>({
baseUrl
: "http://localhost:1506",
}); const
binaryResponse
= await
client
.
get
("/binary-stream")
.
iWantInformationOrThrow
("binary-stream");
binaryResponse
.
onStream
("receiveData", (
chunk
) => {
}); for await (const
chunk
of
binaryResponse
) {
// ... } const
textResponse
= await
client
.
post
(
"/text-stream", {
body
: {
value
: "world" } },
) .
iWantInformationOrThrow
("text-stream");
textResponse
.
onStream
("receiveData", (
chunk
) => {
}); void
textResponse
.
consumeStream
();

To consume the stream, either iterate over the response with for await...of, or call consumeStream(). The receiveData event receives the chunk type that matches the generated client contract.

Released under the MIT License.