Rindle

API index and search · Build metadata

Supporting declarations

packages/react/src/stream.ts. These declarations explain referenced types. Only package-page symbols are package exports.

Exact source

DEFAULT_STREAM_ENDPOINT

/** Where {@link useStreamedText} subscribes by default — `DEFAULT_RINDLE_API_ROUTES.stream`, mirrored
 *  here rather than imported so the browser never pulls `@rindle/api-server`. */
export declare const DEFAULT_STREAM_ENDPOINT = "/api/rindle/stream";

StreamTransport

/**
 * How the live plane is reached. The default ({@link eventSourceTransport}) is SSE, which is what the
 * api-server's `streamFramesToSse` serves and what gets `Last-Event-ID` resume for free. Supply your
 * own for a WebSocket, a fetch-stream, or a test.
 */
export interface StreamTransport {
    /** Attach at `url` and call `onFrame` per decoded frame. MUST return a detach function; it may be
     *  called more than once and must tolerate that. `onFrame` may be called synchronously. */
    subscribe(url: string, onFrame: (frame: StreamFrame) => void): () => void;
}

UseStreamedTextInput

export interface UseStreamedTextInput {
    /** The stream's id — the message row's key. Changing it drops the old tail and rejoins. */
    streamId: string;
    /** What the IVM view shows: `assembleDurableText(message, message.chunks)`. Read from a ref
     *  internally (TRAP 1), so it may change every checkpoint without disturbing the connection. */
    durable: string;
    /** Whether a producer is still running — the app's own read of its status column (typically
     *  `status === "streaming" || status === "pending"`). The live leg attaches only while true. */
    live: boolean;
}

UseStreamedTextOptions

export interface UseStreamedTextOptions {
    /** Default {@link DEFAULT_STREAM_ENDPOINT}. `streamId` and `from` are appended as query params. */
    endpoint?: string;
    /** Default {@link eventSourceTransport}. Read at subscribe time, NOT a dependency — an inline
     *  literal would otherwise reconnect on every render. */
    transport?: StreamTransport;
    /** A frame that could not be decoded, or a transport-level error. The durable plane is unaffected,
     *  so this is a diagnostic, not a failure. */
    onError?: (err: unknown) => void;
}

streamSubscribeUrl

/** `<endpoint>?streamId=…&from=…`. `from` is the join offset; a reconnecting `EventSource` overrides
 *  it with its own `Last-Event-ID` header, which the server prefers. */
export declare function streamSubscribeUrl(endpoint: string, streamId: string, from: number): string;

eventSourceTransport

/** The default SSE transport. Absent `EventSource` (SSR, an older runtime, a test without jsdom) it
 *  attaches nothing and the reader stays on the durable plane — correct, just chunkier. */
export declare function eventSourceTransport(onError?: (err: unknown) => void): StreamTransport;

useStreamedText

/**
 * The response text as it should be rendered right now: the durable prefix spliced with the live
 * tail.
 *
 * ```tsx
 * const data = useFragment(MessageFragment, message);
 * const text = useStreamedText({
 *   streamId: data.id,
 *   durable: assembleDurableText(data, data.chunks),
 *   live: data.status === "streaming" || data.status === "pending",
 * });
 * ```
 *
 * The value is monotone in practice — it only grows while a stream runs — and when the closing
 * checkpoint compacts the chunks into the body it returns the identical string, so there is no
 * flicker at the handoff.
 */
export declare function useStreamedText({ streamId, durable, live }: UseStreamedTextInput, options?: UseStreamedTextOptions): string;