Added 'use' field to the sse client to allow passing of other fetch implementations

This commit is contained in:
2025-03-30 23:51:07 +00:00
committed by Jim Hamill
parent f51f8753a0
commit 20da08d806
+17 -12
View File
@@ -17,7 +17,7 @@ export class SSEClient {
*/ */
public static async from( public static async from(
url: string, url: string,
options: SSEClientOptions, options: Partial<SSEClientOptions> = {},
): Promise<SSEClient> { ): Promise<SSEClient> {
const client = new SSEClient(url, options); const client = new SSEClient(url, options);
await client.connect(); await client.connect();
@@ -35,9 +35,11 @@ export class SSEClient {
* @param url The URL to connect to * @param url The URL to connect to
* @param options Configuration options * @param options Configuration options
*/ */
constructor(url: string, options: SSEClientOptions) { constructor(url: string, options: Partial<SSEClientOptions> = {}) {
this.url = url; this.url = url;
this.options = { this.options = {
// Use default fetch function.
fetch: fetch,
method: 'GET', method: 'GET',
headers: { headers: {
Accept: 'text/event-stream', Accept: 'text/event-stream',
@@ -54,14 +56,6 @@ export class SSEClient {
/** /**
* Connects to the SSE endpoint. * Connects to the SSE endpoint.
*
* @remarks
*
* This currently does not await properly and has a chance of introducing a race-condition.
* We want to wait for the connection to ESTABLISH before resolving.
* Otherwise, there is a slight possibility of missing events during the connection phase.
* If you try to fix this, be cautious about using a while(true) loop: JS is single threaded and you may block.
* Try to use the Streams event features instead.
*/ */
public async connect(): Promise<void> { public async connect(): Promise<void> {
if (this.connected) return; if (this.connected) return;
@@ -82,7 +76,8 @@ export class SSEClient {
// Move the async logic inside a separate function // Move the async logic inside a separate function
const establishConnection = async () => { const establishConnection = async () => {
try { try {
const response = await fetch(this.url, fetchOptions); // Fetch from the provided URL using our fetch function.
const response = await this.options.fetch(this.url, fetchOptions);
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`); throw new Error(`HTTP error! Status: ${response.status}`);
@@ -242,10 +237,20 @@ export class SSEClient {
* Configuration options for the SSEClient. * Configuration options for the SSEClient.
*/ */
export interface SSEClientOptions { export interface SSEClientOptions {
/**
* 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".
*/
fetch: (url: string, options: RequestInit) => Promise<Response>;
/** /**
* HTTP method to use (GET or POST). * HTTP method to use (GET or POST).
*/ */
method?: 'GET' | 'POST'; method: 'GET' | 'POST';
/** /**
* HTTP headers to send with the request. * HTTP headers to send with the request.