Skip to content

Commit

Permalink
Extend onopen/onerror events with the response object (#24)
Browse files Browse the repository at this point in the history
* feat(onerror): add response to the onerror event

* feat(onopen): add response to the onopen event
  • Loading branch information
vlad-tkachenko authored Oct 3, 2024
1 parent daf7843 commit f40bdcb
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
5 changes: 3 additions & 2 deletions src/eventsource.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { http, HttpResponse as MswHttpResponse } from 'msw';
import { server } from '../mocks/node';
import { CustomEventSource as EventSource } from './eventsource';
import { CustomEventSource as EventSource, CustomEvent } from './eventsource';
import DoneCallback = jest.DoneCallback;

describe('EventSource', () => {
Expand Down Expand Up @@ -128,8 +128,9 @@ describe('EventSource', () => {
disableRetry: true,
});

ev.onerror = () => {
ev.onerror = (event: CustomEvent) => {
expect(ev.readyState).toEqual(ev.CLOSED);
expect(event.response?.status).toEqual(401);
done();
};
});
Expand Down
24 changes: 16 additions & 8 deletions src/eventsource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export type EventSourceExtraOptions = {
fetchInput?: typeof fetch;
};

export type CustomEvent = Event & {
response?: Response;
};

export class CustomEventSource extends EventTarget implements EventSource {
// https://html.spec.whatwg.org/multipage/server-sent-events.html#dom-eventsource-url
public url: string;
Expand All @@ -51,12 +55,12 @@ export class CustomEventSource extends EventTarget implements EventSource {
public readyState = this.CONNECTING;

// https://html.spec.whatwg.org/multipage/server-sent-events.html#handler-eventsource-onopen
public onerror: ((this: EventSource, ev: Event) => any) | null = null;
public onerror: ((this: EventSource, ev: CustomEvent) => any) | null = null;
// https://html.spec.whatwg.org/multipage/server-sent-events.html#handler-eventsource-onmessage
public onmessage: ((this: EventSource, ev: MessageEvent) => any) | null =
null;
// https://html.spec.whatwg.org/multipage/server-sent-events.html#handler-eventsource-onerror
public onopen: ((this: EventSource, ev: Event) => any) | null = null;
public onopen: ((this: EventSource, ev: CustomEvent) => any) | null = null;

public onRetryDelayReceived:
| ((this: EventSource, delay: number) => any)
Expand Down Expand Up @@ -141,6 +145,7 @@ export class CustomEventSource extends EventTarget implements EventSource {
if (response.status !== 200) {
return this.failConnection(
`Request failed with status code ${response.status}`,
response,
);
} else if (
!response.headers.get('Content-Type')?.includes(ContentTypeEventStream)
Expand All @@ -149,12 +154,13 @@ export class CustomEventSource extends EventTarget implements EventSource {
`Request failed with wrong content type '${response.headers.get(
'Content-Type',
)}'`,
response,
);
} else if (!response?.body) {
return this.failConnection(`Request failed with empty response body'`);
return this.failConnection(`Request failed with empty response body'`, response);
}

this.announceConnection();
this.announceConnection(response);

const reader: ReadableStreamDefaultReader<Uint8Array> =
response.body.getReader();
Expand Down Expand Up @@ -239,19 +245,21 @@ export class CustomEventSource extends EventTarget implements EventSource {
}

// https://html.spec.whatwg.org/multipage/server-sent-events.html#fail-the-connection
private failConnection(error: unknown) {
private failConnection(error: unknown, response: Response) {
this.logger?.error('Fatal error occurred in EventSource', error);
this.readyState = this.CLOSED;
const event = new Event('error');
const event: CustomEvent = new Event('error');
event.response = response;
this.dispatchEvent(event);
this.onerror?.(event);
}

// https://html.spec.whatwg.org/multipage/server-sent-events.html#announce-the-connection
private announceConnection() {
private announceConnection(response: Response) {
this.logger?.debug('Connection established');
this.readyState = this.OPEN;
const event = new Event('open');
const event: CustomEvent = new Event('open');
event.response = response;
this.dispatchEvent(event);
this.onopen?.(event);
}
Expand Down

0 comments on commit f40bdcb

Please sign in to comment.