200 lines
5.4 KiB
TypeScript
200 lines
5.4 KiB
TypeScript
import type { ExponentialBackoffRunOptions } from '../exponential-backoff/exponential-backoff';
|
|
|
|
export type SSERequestInit = {
|
|
|
|
/**
|
|
* The HTTP method to use.
|
|
*/
|
|
method: 'GET' | 'POST';
|
|
|
|
/**
|
|
* Request headers sent on every connect and reconnect.
|
|
*/
|
|
headers?: Record<string, string>;
|
|
|
|
/**
|
|
* Request body for POST-based SSE endpoints.
|
|
*/
|
|
body?: string | FormData;
|
|
};
|
|
|
|
/**
|
|
* The fetch function to use.
|
|
*
|
|
* NOTE: This is compatible with Browser/Node's native "fetch" function.
|
|
* We use this in place of "typeof fetch" so that we can accept non-standard URLs ("url" is a "string" here).
|
|
* For example, a LibP2P adapter might not use a standardized URL format (and might only include "path").
|
|
* This would cause a type error as native fetch expects type "URL".
|
|
*/
|
|
export type SSERequestFunction = {
|
|
fetch: (url: string, options: RequestInit) => Promise<Response>;
|
|
};
|
|
|
|
/**
|
|
* Lifecycle hooks invoked by {@link SSESession} during connect, read, and teardown.
|
|
*/
|
|
export type SSESessionCallbacks = {
|
|
|
|
/**
|
|
* Called before each fetch so callers can attach auth headers, cookies, or
|
|
* a `Last-Event-ID` for resume semantics.
|
|
*/
|
|
onRequest: (request: RequestInit) => Promise<RequestInit>;
|
|
};
|
|
|
|
export type SSESessionEventCallbacks = {
|
|
|
|
/**
|
|
* Called after the HTTP stream is established and before body reading begins.
|
|
*/
|
|
onConnected: () => void;
|
|
|
|
/**
|
|
* Called when the active transport ends — including {@link SSESession.disconnect},
|
|
* server stream completion, and errors. Not paired with {@link SSESessionEventCallbacks.onConnected}
|
|
* when the initial connect never succeeds.
|
|
*/
|
|
onDisconnected: () => void;
|
|
|
|
/**
|
|
* Called on fetch or read failures. Not invoked for intentional
|
|
* {@link SSESession.disconnect} disconnects.
|
|
*/
|
|
onError: (error: Error) => void;
|
|
};
|
|
|
|
export type SSESessionRetryInterface = {
|
|
|
|
/**
|
|
* Retry policy used while establishing the HTTP connection in
|
|
* {@link SSESession.connect}. Defaults to {@link ExponentialBackoff} with
|
|
* unlimited attempts.
|
|
*/
|
|
retry: {
|
|
run<T>(fn: () => Promise<T>, options?: ExponentialBackoffRunOptions): Promise<T>;
|
|
};
|
|
};
|
|
|
|
export interface SSEParser {
|
|
|
|
/**
|
|
* Incremental SSE frame parser for the response body.
|
|
*
|
|
* {@link SSEEventParser.reset} is called by the session when abandoning a
|
|
* transport so partial frames do not carry over to the next connection.
|
|
*/
|
|
eventParser: {
|
|
parseEvents(buffer: Uint8Array): SSEvent[];
|
|
reset(): void;
|
|
};
|
|
}
|
|
|
|
export type SSELifecycleOptions = {
|
|
|
|
/**
|
|
* When true, {@link SSESession} calls {@link SSESession.connect} again after
|
|
* a transport **error** (not an intentional disconnect).
|
|
* @default true
|
|
*/
|
|
attemptReconnect: boolean;
|
|
|
|
/**
|
|
* When true, {@link SSESession} calls {@link SSESession.connect} again after
|
|
* the **server** closes the stream normally (`done`).
|
|
* @default false
|
|
*/
|
|
persistent: boolean;
|
|
};
|
|
|
|
/**
|
|
* Context from the source that triggered the event.
|
|
*/
|
|
export type SSESessionOperationContext = {
|
|
source?: unknown;
|
|
};
|
|
|
|
/**
|
|
* Discriminated context for the reason the session was disconnected internally.
|
|
*/
|
|
export type SSESessionDisconnectInternalContext = {
|
|
reason: 'disconnect';
|
|
} & SSESessionOperationContext;
|
|
|
|
/**
|
|
* Discriminated context for the reason the session was disconnected remotely.
|
|
*/
|
|
export type SSESessionDisconnectRemoteContext = {
|
|
reason: 'remote';
|
|
};
|
|
|
|
/**
|
|
* Discriminated context for the reason the session was disconnected due to an error.
|
|
*/
|
|
export type SSESessionDisconnectErrorContext = {
|
|
reason: 'error';
|
|
error: Error;
|
|
};
|
|
|
|
/**
|
|
* Discriminated context for the reason the session was disconnected.
|
|
*/
|
|
export type SSESessionDisconnectContext = SSESessionDisconnectInternalContext | SSESessionDisconnectRemoteContext | SSESessionDisconnectErrorContext;
|
|
|
|
/**
|
|
* Events emitted by {@link SSESession}.
|
|
*
|
|
* - `"connected"` — HTTP stream established.
|
|
* - `"message"` — A complete SSE event was parsed.
|
|
* - `"disconnected"` — The active transport ended (including {@link SSESession.disconnect}).
|
|
* - `"error"` — An unexpected fetch or read failure.
|
|
* - `"closed"` — {@link SSESession.close} was called.
|
|
*/
|
|
export type SSESessionEventMap = {
|
|
connected: void;
|
|
beforeDisconnect: SSESessionOperationContext;
|
|
disconnected: SSESessionDisconnectContext;
|
|
error: Error;
|
|
message: SSEvent;
|
|
closed: void;
|
|
};
|
|
|
|
/**
|
|
* Configuration for {@link SSESession}.
|
|
*/
|
|
export type SSESessionOptions = SSESessionCallbacks
|
|
& SSERequestInit
|
|
& SSERequestFunction
|
|
& SSESessionRetryInterface
|
|
& SSELifecycleOptions
|
|
& SSEParser;
|
|
|
|
/**
|
|
* Represents a Server-Sent Event.
|
|
*/
|
|
export interface SSEvent {
|
|
|
|
/**
|
|
* Event data.
|
|
*/
|
|
data: string;
|
|
|
|
/**
|
|
* Event type.
|
|
* This value is optionally sent by the server. Traditional EventSource allows listeners for specific event types.
|
|
* The SSE Session collapses all event types into "message" event.
|
|
*/
|
|
event?: string;
|
|
|
|
/**
|
|
* Event ID.
|
|
* This value is optionally sent by the server as a "checkpoint" the client can use to resume from using the Last-Event-ID header.
|
|
*/
|
|
id?: string;
|
|
|
|
/**
|
|
* Reconnection time in milliseconds.
|
|
* This value is optionally sent by the server to indicate the server's preferred time before reconnecting
|
|
*/
|
|
retry?: number;
|
|
}
|