From 20da08d806bfd5d34bb73dd42628630510453894 Mon Sep 17 00:00:00 2001 From: Harvey Zuccon Date: Sun, 30 Mar 2025 23:51:07 +0000 Subject: [PATCH] Added 'use' field to the sse client to allow passing of other fetch implementations --- packages/stack/src/utils/sse-client.ts | 29 +++++++++++++++----------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/stack/src/utils/sse-client.ts b/packages/stack/src/utils/sse-client.ts index 3ce2dab..0c299f9 100644 --- a/packages/stack/src/utils/sse-client.ts +++ b/packages/stack/src/utils/sse-client.ts @@ -17,7 +17,7 @@ export class SSEClient { */ public static async from( url: string, - options: SSEClientOptions, + options: Partial = {}, ): Promise { const client = new SSEClient(url, options); await client.connect(); @@ -35,9 +35,11 @@ export class SSEClient { * @param url The URL to connect to * @param options Configuration options */ - constructor(url: string, options: SSEClientOptions) { + constructor(url: string, options: Partial = {}) { this.url = url; this.options = { + // Use default fetch function. + fetch: fetch, method: 'GET', headers: { Accept: 'text/event-stream', @@ -54,14 +56,6 @@ export class SSEClient { /** * 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 { if (this.connected) return; @@ -82,7 +76,8 @@ export class SSEClient { // Move the async logic inside a separate function const establishConnection = async () => { 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) { throw new Error(`HTTP error! Status: ${response.status}`); @@ -242,10 +237,20 @@ export class SSEClient { * Configuration options for the SSEClient. */ 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; + /** * HTTP method to use (GET or POST). */ - method?: 'GET' | 'POST'; + method: 'GET' | 'POST'; /** * HTTP headers to send with the request.