Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/content/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default withMermaid(defineConfig({
{ text: 'Context', link: '/docs/context' },
{ text: 'Error Handling', link: '/docs/error-handling' },
{ text: 'Binary Data', link: '/docs/binary-data' },
{ text: 'Event Iterator (SSE)', link: '/docs/event-iterator' },
{ text: 'AsyncIteratorObject (SSE)', link: '/docs/async-iterator-object' },
{ text: 'Metadata', link: '/docs/metadata' },
{ text: 'Playgrounds', link: '/docs/playgrounds' },
{
Expand Down Expand Up @@ -131,7 +131,7 @@ export default withMermaid(defineConfig({
{ text: 'Server-Side', link: '/docs/client/server-side' },
{ text: 'Client-Side', link: '/docs/client/client-side' },
{ text: 'Error Handling', link: '/docs/client/error-handling' },
{ text: 'Event Iterator', link: '/docs/client/event-iterator' },
{ text: 'AsyncIteratorObject (SSE)', link: '/docs/client/async-iterator-object' },
{ text: 'Dynamic Link', link: '/docs/client/dynamic-link' },
],
},
Expand Down
4 changes: 2 additions & 2 deletions apps/content/docs/adapters/fetch-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ The examples above only show how to configure the link. For examples of creating

## Event Stream Options

You can configure how [event iterators](/docs/event-iterator) are streamed to the client using the `toFetchResponse.eventStream` options when creating the handler.
You can configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed to the client using the `toFetchResponse.eventStream` options when creating the handler.

```ts
const handler = new OpenAPIHandler(router, {
Expand Down Expand Up @@ -209,5 +209,5 @@ const handler = new OpenAPIHandler(router, {
```

::: info
You can also configure how [event iterators](/docs/event-iterator) are streamed from client to server using `toFetchRequest.eventStream` options when creating the link. However, this is rarely used because streaming requests are not widely supported in browsers and may require manually overriding the `fetch` function with `duplex`.
You can also configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed from client to server using `toFetchRequest.eventStream` options when creating the link. However, this is rarely used because streaming requests are not widely supported in browsers and may require manually overriding the `fetch` function with `duplex`.
:::
2 changes: 1 addition & 1 deletion apps/content/docs/adapters/node-http.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ server.listen(3000, '127.0.0.1', () => console.log('Listening on 127.0.0.1:3000'

## Event Stream Options

You can configure how [event iterators](/docs/event-iterator) are streamed to the client using the `sendStandardResponse.eventStream` options when creating the handler.
You can configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed to the client using the `sendStandardResponse.eventStream` options when creating the handler.

```ts
const handler = new OpenAPIHandler(router, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Event Iterator (SSE)
# AsyncIteratorObject (SSE)

Event Iterator enables **typesafe**, **realtime data streaming**. It is the recommended approach for building features like live notifications, chat messages, progress updates, and data feeds.
AsyncIteratorObject enables **typesafe**, **realtime data streaming**. It is the recommended approach for building features like live notifications, chat messages, progress updates, and data feeds.

## Overview

An event iterator is implemented as an [asynchronous generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function*) (or a compatible implementation). In the example below, the handler emits a new event every second:
An `AsyncIteratorObject` is implemented as an [asynchronous generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function*) (or a compatible implementation). In the example below, the handler emits a new event every second:

```ts
const example = os
Expand All @@ -18,18 +18,18 @@ const example = os
```

::: info
Learn how to consume event iterators from the client in the [client guide](/docs/client/event-iterator).
Learn how to consume an `AsyncIteratorObject` from the client in the [client guide](/docs/client/async-iterator-object).
:::

## Validating Events

Use the built‑in `eventIterator` helper that works with any [Standard Schema](https://standardschema.dev/schema#what-schema-libraries-implement-the-spec) library to validate events.
Use the built‑in `asyncIteratorObject` schema that works with any [Standard Schema](https://standardschema.dev/schema#what-schema-libraries-implement-the-spec) library to validate events.

```ts
import { eventIterator } from '@orpc/server'
import { asyncIteratorObject } from '@orpc/server'

const example = os
.output(eventIterator(z.object({ message: z.string() })))
.output(asyncIteratorObject(z.object({ message: z.string() })))
.handler(async function* ({ input, signal, lastEventId }) {
while (true) {
signal?.throwIfAborted()
Expand Down Expand Up @@ -68,7 +68,7 @@ const example = os
})
```

## Stop Event Iterator
## Stop AsyncIteratorObject

To end the stream, use either a `return` or `throw` statement. oRPC marks the stream as completed when the handler returns.

Expand Down Expand Up @@ -114,7 +114,7 @@ const example = os

## Publisher Helper

You can combine the event iterator with the [Publisher Helper](/docs/helpers/publisher) to build real-time features like chat, notifications, or live updates with resume support.
You can combine the [AsyncIteratorObject](/docs/async-iterator-object) with the [Publisher Helper](/docs/helpers/publisher) to build real-time features like chat, notifications, or live updates with resume support.

```ts
const publisher = new MemoryPublisher<{
Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/binary-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const example = os
})
```

## `ReadableStream<Uint8Array>`
## ReadableStream\<Uint8Array\>

Procedures can return `ReadableStream<Uint8Array>` to stream binary responses. The example below uses the [Response Headers Plugin](/docs/plugins/response-headers) to set the appropriate `Content-Type` header.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Event Iterator in Client
# AsyncIteratorObject in Client

Consume an [Event Iterator](/docs/event-iterator) like an [AsyncGenerator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). Await the call, then iterate over events as they arrive.
Consume an [AsyncIteratorObject](/docs/async-iterator-object) like an [AsyncGenerator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator). Await the call, then iterate over events as they arrive.

## Basic Usage

```ts twoslash
import { eventIterator, oc, RouterContractClient } from '@orpc/contract'
import { asyncIteratorObject, oc, RouterContractClient } from '@orpc/contract'
import { z } from 'zod'

const contract = {
streaming: oc.output(eventIterator(z.object({ message: z.string() })))
streaming: oc.output(asyncIteratorObject(z.object({ message: z.string() })))
}

declare const client: RouterContractClient<typeof contract>
Expand Down Expand Up @@ -44,7 +44,7 @@ for await (const event of iterator) {
## Error Handling

::: info
Unlike traditional SSE, Event Iterators do not retry automatically after an error. To add retries, use the [Retry Plugin](/docs/plugins/retry#event-source-simulation).
Unlike traditional SSE, AsyncIteratorObjects do not retry automatically after an error. To add retries, use the [Retry Plugin](/docs/plugins/retry#event-source-simulation).
:::

```ts
Expand Down Expand Up @@ -77,14 +77,14 @@ for await (const event of iterator) {
}
```

## Using `consumeEventIterator`
## Using `consumeAsyncIterator`

Use `consumeEventIterator` to consume an event iterator with lifecycle callbacks. It accepts either an event iterator or a promise that resolves to one.
Use `consumeAsyncIterator` to consume an `AsyncIterator` with lifecycle callbacks. It accepts either an iterator or a promise that resolves to one.

```ts
import { consumeEventIterator } from '@orpc/client'
import { consumeAsyncIterator } from '@orpc/client'

const cancel = consumeEventIterator(client.streaming(), {
const cancel = consumeAsyncIterator(client.streaming(), {
onEvent: (event) => {
console.log(event.message)
},
Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/integrations/nest.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ Procedures run only when a matching NestJS controller method is called. If no ro

### Event Stream Options

Configure how [event iterators](/docs/event-iterator) are streamed to the client using the `toNestResponse.eventStream` options.
Configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed to the client using the `toNestResponse.eventStream` options.

```ts
@Module({
Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/integrations/opentelemetry.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Define the `name` property on your middleware to improve span naming and make tr

## Capture Abort Signals

If your application heavily uses [Event Iterator](/docs/event-iterator) or similar streaming patterns, we recommend capturing an event when the `signal` is aborted to properly track and detach unexpected long-running operations:
If your application heavily uses [AsyncIteratorObject](/docs/async-iterator-object) or similar streaming patterns, we recommend capturing an event when the `signal` is aborted to properly track and detach unexpected long-running operations:

```ts
import { trace } from '@opentelemetry/api'
Expand Down
4 changes: 2 additions & 2 deletions apps/content/docs/integrations/tanstack-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ const query = useQuery(orpc.planet.find.queryOptions({

## Streamed Query Options

Use `.streamedOptions` to build streamed query options for [Event Iterator](/docs/event-iterator). The resulting data is an array of events, and each new event is appended as it arrives.
Use `.streamedOptions` to build streamed query options for an [AsyncIteratorObject](/docs/async-iterator-object). The resulting data is an array of events, and each new event is appended as it arrives.

It works with `useQuery`, `useSuspenseQuery`, and `prefetchQuery`, and any other API that accepts query options.

Expand Down Expand Up @@ -117,7 +117,7 @@ const query = useQuery(orpc.streamed.streamedOptions({

## Live Query Options

Use `.liveOptions` to build live query options for [Event Iterator](/docs/event-iterator). The data always reflects the latest event, replacing the previous value whenever a new one arrives.
Use `.liveOptions` to build live query options for an [AsyncIteratorObject](/docs/async-iterator-object). The data always reflects the latest event, replacing the previous value whenever a new one arrives.

It works with `useQuery`, `useSuspenseQuery`, and `prefetchQuery`, and any other API that accepts query options.

Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/openapi/handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ If you use `OpenAPILink` with a custom server-side error format, make sure to co

## Event Stream Options

Configure how [event iterators](/docs/event-iterator) are streamed to the client. Available options depend on the adapter. For example, the fetch adapter supports:
Configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed to the client. Available options depend on the adapter. For example, the fetch adapter supports:

```ts
const handler = new OpenAPIHandler(router, {
Expand Down
18 changes: 9 additions & 9 deletions apps/content/docs/openapi/input-and-output-mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,15 @@ const uploadLargeFile = os

Supported body hints:

| Hint | Parsed Result |
| ------------------- | --------------------------------------------------------------------------------- |
| `json` | JSON value |
| `form-data` | `FormData` decoded with [bracket notation](/docs/openapi/bracket-notation) |
| `url-search-params` | `URLSearchParams` decoded with [bracket notation](/docs/openapi/bracket-notation) |
| `event-stream` | [Event Iterator](/docs/event-iterator) |
| `octet-stream` | `ReadableStream<Uint8Array>` for streamed binary data |
| `file` | `File` for binary data |
| `none` | `undefined` |
| Hint | Parsed Result |
| ------------------- | --------------------------------------------------------------------------------------------------- |
| `json` | JSON value |
| `form-data` | `FormData` decoded with [bracket notation](/docs/openapi/bracket-notation) |
| `url-search-params` | `URLSearchParams` decoded with [bracket notation](/docs/openapi/bracket-notation) |
| `event-stream` | [AsyncIteratorObject](/docs/async-iterator-object) |
| `octet-stream` | [ReadableStream\<Uint8Array\>](/docs/binary-data#readablestreamuint8array) for streamed binary data |
| `file` | `File` for binary data |
| `none` | `undefined` |

::: info
Learn more about body hints in the [Standard Server documentation](https://github.com/middleapi/standardserver#standard-body)
Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/openapi/link.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ const link = new OpenAPILink(contract, {

## Event Stream Options

Configure how [event iterators](/docs/event-iterator) are streamed to the server. Available options depend on the adapter. For example, the fetch adapter supports:
Configure how an [AsyncIteratorObject](/docs/async-iterator-object) is streamed to the server. Available options depend on the adapter. For example, the fetch adapter supports:

```ts
const link = new OpenAPILink(contract, {
Expand Down
44 changes: 22 additions & 22 deletions apps/content/docs/openapi/serializer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ OpenAPI Serializers handle one-way serialization to JSON-friendly formats. They

`OpenAPISerializer` supports the following types by default:

| Type | Handler key | Serialized | Notes |
| ---------------------------------------- | ----------- | ------------------ | ----------------------------- |
| **string** | | | |
| **number** | | | |
| **NaN** | `nan` | `null` | |
| **boolean** | | | |
| **null** | | | |
| **undefined** | `undefined` | `null` | Ignore `undefined` properties |
| **Date** | `date` | ISO String, `null` | |
| **BigInt** | `bigint` | string | |
| **RegExp** | `regexp` | string | |
| **URL** | `url` | string | |
| **Record (object)** | | | `toJSON` methods are ignored |
| **Array** | | | |
| **Set** | `set` | array | |
| **Map** | `map` | array | |
| **Blob** | | | Unsupported in Event Iterator |
| **File** | | | Unsupported in Event Iterator |
| **Event Iterator (AsyncIteratorObject)** | | | Only at the root level |
| **ReadableStream\<Uint8Array\>** | | | Only at the root level |
| Type | Handler key | Serialized | Notes |
| -------------------------------- | ----------- | ------------------ | ------------------------------------ |
| **string** | | | |
| **number** | | | |
| **NaN** | `nan` | `null` | |
| **boolean** | | | |
| **null** | | | |
| **undefined** | `undefined` | `null` | Ignore `undefined` properties |
| **Date** | `date` | ISO String, `null` | |
| **BigInt** | `bigint` | string | |
| **RegExp** | `regexp` | string | |
| **URL** | `url` | string | |
| **Record (object)** | | | `toJSON` methods are ignored |
| **Array** | | | |
| **Set** | `set` | array | |
| **Map** | `map` | array | |
| **Blob** | | | Unsupported in `AsyncIteratorObject` |
| **File** | | | Unsupported in `AsyncIteratorObject` |
| **AsyncIteratorObject** | | | Only at the root level |
| **ReadableStream\<Uint8Array\>** | | | Only at the root level |

<!--@include: @/shared/standard-server-cors-warning.md -->

Expand Down Expand Up @@ -128,9 +128,9 @@ Standard-Server: file
If the receiver mistakenly handles this payload as a regular (non-file) body, set the `standard-server` header to help the receiver detect the actual data type and handle it correctly. Learn more about this header in the [Standard Server Documentation](https://github.com/middleapi/standardserver#resolving-body).
:::

### Event Iterator (AsyncIteratorObject)
### AsyncIteratorObject

When the output is an event iterator (`AsyncIteratorObject`), it is sent as a [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) stream. Each event contains one serialized chunk of data.
When the output is an `AsyncIteratorObject`, it is sent as a [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) stream. Each event contains one serialized chunk of data.

```http
HTTP/1.1 200 OK
Expand Down
2 changes: 1 addition & 1 deletion apps/content/docs/plugins/retry.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const link = new RPCLink<ClientContext>({

## Event Source Simulation

To replicate the behavior of [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) for [Event Iterator](/docs/event-iterator), use the following configuration:
To replicate the behavior of [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) for an [AsyncIteratorObject](/docs/async-iterator-object), use the following configuration:

```ts
const streaming = await client.streaming('the input', {
Expand Down
Loading
Loading