Merge branch 'sse-fetch-injection' into 'development'

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

See merge request GeneralProtocols/xo/stack!52
This commit is contained in:
Jim Hamill
2025-03-30 23:51:07 +00:00
+17 -12
View File
@@ -17,7 +17,7 @@ export class SSEClient {
*/
public static async from(
url: string,
options: SSEClientOptions,
options: Partial<SSEClientOptions> = {},
): Promise<SSEClient> {
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<SSEClientOptions> = {}) {
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<void> {
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<Response>;
/**
* HTTP method to use (GET or POST).
*/
method?: 'GET' | 'POST';
method: 'GET' | 'POST';
/**
* HTTP headers to send with the request.