reconnecting-eventsource 1.4.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,7 +23,7 @@ npm install reconnecting-eventsource
23
23
  In a browser environment, bring this in using:
24
24
 
25
25
  ```html
26
- <script src="/node_modules/reconnecting-eventsource/dist/ReconnectingEventSource[.min].js"></script>
26
+ <script src="/node_modules/reconnecting-eventsource/dist/ReconnectingEventSource.min.js"></script>
27
27
  ```
28
28
 
29
29
  (You are free to copy this file out of `node_modules` if you wish)
@@ -52,7 +52,6 @@ Like the [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventS
52
52
  // underlying EventSource class, default `EventSource`
53
53
  eventSourceClass: EventSource,
54
54
  }
55
-
56
55
  ```
57
56
 
58
57
  ## Building from source
@@ -0,0 +1,44 @@
1
+ /// <reference types="node" />
2
+ export interface ReconnectingEventSourceInit extends EventSourceInit {
3
+ max_retry_time?: number;
4
+ eventSourceClass?: typeof EventSource;
5
+ lastEventId?: string;
6
+ }
7
+ export declare class EventSourceNotAvailableError extends Error {
8
+ constructor();
9
+ }
10
+ declare type Listeners = {
11
+ [name: string]: ((this: EventSource, event: Event) => any)[];
12
+ };
13
+ export default class ReconnectingEventSource implements EventSource {
14
+ readonly _configuration: ReconnectingEventSourceInit | undefined;
15
+ readonly CONNECTING = 0;
16
+ readonly OPEN = 1;
17
+ readonly CLOSED = 2;
18
+ _eventSource: EventSource | null;
19
+ _lastEventId: string | null;
20
+ _timer: NodeJS.Timer | null;
21
+ _listeners: Listeners;
22
+ _onevent_wrapped: (this: EventSource, ev: Event) => any;
23
+ readyState: 0 | 1 | 2;
24
+ url: string;
25
+ withCredentials: boolean;
26
+ readonly max_retry_time: number;
27
+ eventSourceClass: typeof EventSource;
28
+ constructor(url: string | URL, configuration?: ReconnectingEventSourceInit);
29
+ dispatchEvent(event: Event): boolean;
30
+ _start(): void;
31
+ _onopen(event: Event): void;
32
+ _onerror(event: Event): void;
33
+ _onevent(event: Event): void;
34
+ onopen(event: Event): void;
35
+ onerror(event: Event): void;
36
+ onmessage(event: MessageEvent): void;
37
+ close(): void;
38
+ addEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
39
+ addEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | AddEventListenerOptions): void;
40
+ removeEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
41
+ removeEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | EventListenerOptions): void;
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=reconnecting-eventsource.d.ts.map
@@ -0,0 +1,259 @@
1
+ // MIT License:
2
+ //
3
+ // Copyright (C) 2022 Fanout, Inc.
4
+ //
5
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ // of this software and associated documentation files (the "Software"), to
7
+ // deal in the Software without restriction, including without limitation the
8
+ // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
+ // sell copies of the Software, and to permit persons to whom the Software is
10
+ // furnished to do so, subject to the following conditions:
11
+ //
12
+ // The above copyright notice and this permission notice shall be included in
13
+ // all copies or substantial portions of the Software.
14
+ //
15
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
+ // IN THE SOFTWARE.
22
+ var __extends = (this && this.__extends) || (function () {
23
+ var extendStatics = function (d, b) {
24
+ extendStatics = Object.setPrototypeOf ||
25
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
26
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
27
+ return extendStatics(d, b);
28
+ };
29
+ return function (d, b) {
30
+ if (typeof b !== "function" && b !== null)
31
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
32
+ extendStatics(d, b);
33
+ function __() { this.constructor = d; }
34
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
35
+ };
36
+ })();
37
+ var __values = (this && this.__values) || function(o) {
38
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
39
+ if (m) return m.call(o);
40
+ if (o && typeof o.length === "number") return {
41
+ next: function () {
42
+ if (o && i >= o.length) o = void 0;
43
+ return { value: o && o[i++], done: !o };
44
+ }
45
+ };
46
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
47
+ };
48
+ var __read = (this && this.__read) || function (o, n) {
49
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
50
+ if (!m) return o;
51
+ var i = m.call(o), r, ar = [], e;
52
+ try {
53
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
54
+ }
55
+ catch (error) { e = { error: error }; }
56
+ finally {
57
+ try {
58
+ if (r && !r.done && (m = i["return"])) m.call(i);
59
+ }
60
+ finally { if (e) throw e.error; }
61
+ }
62
+ return ar;
63
+ };
64
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
65
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
66
+ if (ar || !(i in from)) {
67
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
68
+ ar[i] = from[i];
69
+ }
70
+ }
71
+ return to.concat(ar || Array.prototype.slice.call(from));
72
+ };
73
+ var EventSourceNotAvailableError = /** @class */ (function (_super) {
74
+ __extends(EventSourceNotAvailableError, _super);
75
+ function EventSourceNotAvailableError() {
76
+ return _super.call(this, 'EventSource not available.\n' +
77
+ 'Consider loading an EventSource polyfill and making it available globally as EventSource, ' +
78
+ 'or passing one in as eventSourceClass to the ReconnectingEventSource constructor.') || this;
79
+ }
80
+ return EventSourceNotAvailableError;
81
+ }(Error));
82
+ export { EventSourceNotAvailableError };
83
+ var ReconnectingEventSource = /** @class */ (function () {
84
+ function ReconnectingEventSource(url, configuration) {
85
+ var _this = this;
86
+ this.CONNECTING = 0;
87
+ this.OPEN = 1;
88
+ this.CLOSED = 2;
89
+ this._configuration = configuration != null ? Object.assign({}, configuration) : undefined;
90
+ this.withCredentials = false;
91
+ this._eventSource = null;
92
+ this._lastEventId = null;
93
+ this._timer = null;
94
+ this._listeners = {};
95
+ this.url = url.toString();
96
+ this.readyState = this.CONNECTING;
97
+ this.max_retry_time = 3000;
98
+ this.eventSourceClass = globalThis.EventSource;
99
+ if (this._configuration != null) {
100
+ if (this._configuration.lastEventId) {
101
+ this._lastEventId = this._configuration.lastEventId;
102
+ delete this._configuration['lastEventId'];
103
+ }
104
+ if (this._configuration.max_retry_time) {
105
+ this.max_retry_time = this._configuration.max_retry_time;
106
+ delete this._configuration['max_retry_time'];
107
+ }
108
+ if (this._configuration.eventSourceClass) {
109
+ this.eventSourceClass = this._configuration.eventSourceClass;
110
+ delete this._configuration['eventSourceClass'];
111
+ }
112
+ }
113
+ if (this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {
114
+ throw new EventSourceNotAvailableError();
115
+ }
116
+ this._onevent_wrapped = function (event) { _this._onevent(event); };
117
+ this._start();
118
+ }
119
+ ReconnectingEventSource.prototype.dispatchEvent = function (event) {
120
+ throw new Error("Method not implemented.");
121
+ };
122
+ ReconnectingEventSource.prototype._start = function () {
123
+ var e_1, _a;
124
+ var _this = this;
125
+ var url = this.url;
126
+ if (this._lastEventId) {
127
+ if (url.indexOf('?') === -1) {
128
+ url += '?';
129
+ }
130
+ else {
131
+ url += '&';
132
+ }
133
+ url += 'lastEventId=' + encodeURIComponent(this._lastEventId);
134
+ }
135
+ this._eventSource = new this.eventSourceClass(url, this._configuration);
136
+ this._eventSource.onopen = function (event) { _this._onopen(event); };
137
+ this._eventSource.onerror = function (event) { _this._onerror(event); };
138
+ this._eventSource.onmessage = function (event) { _this.onmessage(event); };
139
+ try {
140
+ // apply listen types
141
+ for (var _b = __values(Object.keys(this._listeners)), _c = _b.next(); !_c.done; _c = _b.next()) {
142
+ var type = _c.value;
143
+ this._eventSource.addEventListener(type, this._onevent_wrapped);
144
+ }
145
+ }
146
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
147
+ finally {
148
+ try {
149
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
150
+ }
151
+ finally { if (e_1) throw e_1.error; }
152
+ }
153
+ };
154
+ ReconnectingEventSource.prototype._onopen = function (event) {
155
+ if (this.readyState === 0) {
156
+ this.readyState = 1;
157
+ this.onopen(event);
158
+ }
159
+ };
160
+ ReconnectingEventSource.prototype._onerror = function (event) {
161
+ var _this = this;
162
+ if (this.readyState === 1) {
163
+ this.readyState = 0;
164
+ this.onerror(event);
165
+ }
166
+ if (this._eventSource) {
167
+ if (this._eventSource.readyState === 2) {
168
+ // reconnect with new object
169
+ this._eventSource.close();
170
+ this._eventSource = null;
171
+ // reconnect after random timeout < max_retry_time
172
+ var timeout = Math.round(this.max_retry_time * Math.random());
173
+ this._timer = setTimeout(function () { return _this._start(); }, timeout);
174
+ }
175
+ }
176
+ };
177
+ ReconnectingEventSource.prototype._onevent = function (event) {
178
+ var e_2, _a;
179
+ if (event instanceof MessageEvent) {
180
+ this._lastEventId = event.lastEventId;
181
+ }
182
+ var listenersForType = this._listeners[event.type];
183
+ if (listenersForType != null) {
184
+ try {
185
+ // operate on a copy
186
+ for (var _b = __values(__spreadArray([], __read(listenersForType), false)), _c = _b.next(); !_c.done; _c = _b.next()) {
187
+ var listener = _c.value;
188
+ listener.call(this, event);
189
+ }
190
+ }
191
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
192
+ finally {
193
+ try {
194
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
195
+ }
196
+ finally { if (e_2) throw e_2.error; }
197
+ }
198
+ }
199
+ if (event.type === 'message') {
200
+ this.onmessage(event);
201
+ }
202
+ };
203
+ ReconnectingEventSource.prototype.onopen = function (event) {
204
+ // may be overridden
205
+ };
206
+ ReconnectingEventSource.prototype.onerror = function (event) {
207
+ // may be overridden
208
+ };
209
+ ReconnectingEventSource.prototype.onmessage = function (event) {
210
+ // may be overridden
211
+ };
212
+ ReconnectingEventSource.prototype.close = function () {
213
+ if (this._timer) {
214
+ clearTimeout(this._timer);
215
+ this._timer = null;
216
+ }
217
+ if (this._eventSource) {
218
+ this._eventSource.close();
219
+ this._eventSource = null;
220
+ }
221
+ this.readyState = 2;
222
+ };
223
+ ReconnectingEventSource.prototype.addEventListener = function (type, listener, options) {
224
+ // We don't support the options arg at the moment
225
+ if (!(type in this._listeners)) {
226
+ this._listeners[type] = [];
227
+ if (this._eventSource != null) {
228
+ this._eventSource.addEventListener(type, this._onevent_wrapped);
229
+ }
230
+ }
231
+ var listenersForType = this._listeners[type];
232
+ if (Array.isArray(listenersForType) && !listenersForType.includes(listener)) {
233
+ listenersForType.push(listener);
234
+ }
235
+ };
236
+ ReconnectingEventSource.prototype.removeEventListener = function (type, listener, options) {
237
+ // We don't support the options arg at the moment
238
+ var listenersForType = this._listeners[type];
239
+ if (listenersForType != null) {
240
+ // eslint-disable-next-line no-constant-condition
241
+ while (true) {
242
+ var index = listenersForType.indexOf(listener);
243
+ if (index === -1) {
244
+ break;
245
+ }
246
+ listenersForType.splice(index, 1);
247
+ }
248
+ if (listenersForType.length <= 0) {
249
+ delete this._listeners[type];
250
+ if (this._eventSource != null) {
251
+ this._eventSource.removeEventListener(type, this._onevent_wrapped);
252
+ }
253
+ }
254
+ }
255
+ };
256
+ return ReconnectingEventSource;
257
+ }());
258
+ export default ReconnectingEventSource;
259
+ //# sourceMappingURL=reconnecting-eventsource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconnecting-eventsource.js","sourceRoot":"","sources":["../../src/reconnecting-eventsource.ts"],"names":[],"mappings":"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","sourcesContent":["// MIT License:\n//\n// Copyright (C) 2022 Fanout, Inc.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to\n// deal in the Software without restriction, including without limitation the\n// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n// sell copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n// IN THE SOFTWARE.\n\nexport interface ReconnectingEventSourceInit extends EventSourceInit {\n // the maximum time to wait before attempting to reconnect in ms, default `3000`\n // note: wait time is randomised to prevent all clients from attempting to reconnect simultaneously\n max_retry_time?: number;\n\n // the EventSource class to wrap. This allows the use of a polyfill or alternate\n // implementation instead of the platform-provided EventSource class.\n eventSourceClass?: typeof EventSource;\n\n // the last event\n lastEventId?: string;\n}\n\nexport class EventSourceNotAvailableError extends Error {\n constructor() {\n super(\n 'EventSource not available.\\n' +\n 'Consider loading an EventSource polyfill and making it available globally as EventSource, ' +\n 'or passing one in as eventSourceClass to the ReconnectingEventSource constructor.'\n );\n }\n}\n\ntype EventType<T extends string> = T extends keyof EventSourceEventMap ? EventSourceEventMap[T] : MessageEvent<any>;\ntype EventListenerType<T extends string> = (this: EventSource, event: EventType<T>) => any;\n\ntype Listeners = {\n [name: string]: ((this: EventSource, event: Event) => any)[];\n};\n\nexport default class ReconnectingEventSource implements EventSource {\n\n readonly _configuration: ReconnectingEventSourceInit | undefined;\n readonly CONNECTING = 0;\n readonly OPEN = 1;\n readonly CLOSED = 2;\n\n _eventSource: EventSource | null;\n _lastEventId: string | null;\n _timer: NodeJS.Timer | null;\n _listeners: Listeners;\n _onevent_wrapped: (this: EventSource, ev: Event) => any;\n\n readyState: 0 | 1 | 2;\n url: string;\n withCredentials: boolean;\n\n readonly max_retry_time: number;\n eventSourceClass: typeof EventSource;\n\n constructor(url: string | URL, configuration?: ReconnectingEventSourceInit) {\n this._configuration = configuration != null ? Object.assign({}, configuration) : undefined;\n this.withCredentials = false;\n\n this._eventSource = null;\n this._lastEventId = null;\n this._timer = null;\n this._listeners = {};\n\n this.url = url.toString();\n this.readyState = this.CONNECTING;\n this.max_retry_time = 3000;\n this.eventSourceClass = globalThis.EventSource;\n\n if (this._configuration != null) {\n if (this._configuration.lastEventId) {\n this._lastEventId = this._configuration.lastEventId;\n delete this._configuration['lastEventId'];\n }\n\n if (this._configuration.max_retry_time) {\n this.max_retry_time = this._configuration.max_retry_time;\n delete this._configuration['max_retry_time'];\n }\n\n if (this._configuration.eventSourceClass) {\n this.eventSourceClass = this._configuration.eventSourceClass;\n delete this._configuration['eventSourceClass'];\n }\n }\n\n if(this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {\n throw new EventSourceNotAvailableError();\n }\n\n this._onevent_wrapped = (event) => { this._onevent(event); };\n\n this._start();\n }\n\n dispatchEvent(event: Event): boolean {\n throw new Error(\"Method not implemented.\");\n }\n\n _start() {\n let url = this.url;\n\n if (this._lastEventId) {\n if (url.indexOf('?') === -1) {\n url += '?';\n } else {\n url += '&';\n }\n url += 'lastEventId=' + encodeURIComponent(this._lastEventId);\n }\n\n this._eventSource = new this.eventSourceClass(url, this._configuration);\n\n this._eventSource.onopen = (event) => { this._onopen(event); };\n this._eventSource.onerror = (event) => { this._onerror(event); };\n this._eventSource.onmessage = (event) => { this.onmessage(event); };\n\n // apply listen types\n for (const type of Object.keys(this._listeners)) {\n this._eventSource.addEventListener(type, this._onevent_wrapped);\n }\n }\n\n _onopen(event: Event) {\n if (this.readyState === 0) {\n this.readyState = 1;\n this.onopen(event);\n }\n }\n\n _onerror(event: Event) {\n if (this.readyState === 1) {\n this.readyState = 0;\n this.onerror(event);\n }\n\n if (this._eventSource) {\n if(this._eventSource.readyState === 2) {\n // reconnect with new object\n this._eventSource.close();\n this._eventSource = null;\n\n // reconnect after random timeout < max_retry_time\n const timeout = Math.round(this.max_retry_time * Math.random());\n this._timer = setTimeout(() => this._start(), timeout);\n }\n }\n }\n\n _onevent(event: Event) {\n if (event instanceof MessageEvent) {\n this._lastEventId = event.lastEventId;\n }\n\n const listenersForType = this._listeners[event.type];\n if (listenersForType != null) {\n // operate on a copy\n for (const listener of [...listenersForType]) {\n listener.call(this, event);\n }\n }\n\n if (event.type === 'message') {\n this.onmessage(event as MessageEvent);\n }\n }\n\n onopen(event: Event) {\n // may be overridden\n }\n\n onerror(event: Event) {\n // may be overridden\n }\n\n onmessage(event: MessageEvent) {\n // may be overridden\n }\n\n close() {\n if (this._timer) {\n clearTimeout(this._timer);\n this._timer = null;\n }\n\n if (this._eventSource) {\n this._eventSource.close();\n this._eventSource = null;\n }\n\n this.readyState = 2;\n }\n\n addEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;\n addEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | AddEventListenerOptions): void;\n addEventListener<K extends string>(type: K, listener: EventListenerType<K>, options?: boolean | AddEventListenerOptions): void {\n // We don't support the options arg at the moment\n\n if (!(type in this._listeners)) {\n this._listeners[type] = [];\n if (this._eventSource != null) {\n this._eventSource.addEventListener(type, this._onevent_wrapped);\n }\n }\n\n const listenersForType = this._listeners[type] as EventListenerType<K>[];\n if (Array.isArray(listenersForType) && !listenersForType.includes(listener)) {\n listenersForType.push(listener);\n }\n }\n\n removeEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | EventListenerOptions): void;\n removeEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | EventListenerOptions): void;\n removeEventListener<K extends string>(type: K, listener: EventListenerType<K>, options?: boolean | EventListenerOptions): void {\n // We don't support the options arg at the moment\n\n const listenersForType = this._listeners[type] as EventListenerType<K>[];\n if (listenersForType != null) {\n // eslint-disable-next-line no-constant-condition\n while(true) {\n const index = listenersForType.indexOf(listener);\n if (index === -1) {\n break;\n }\n listenersForType.splice(index, 1);\n }\n\n if (listenersForType.length <= 0) {\n delete this._listeners[type];\n if (this._eventSource != null) {\n this._eventSource.removeEventListener(type, this._onevent_wrapped);\n }\n }\n }\n }\n}\n"]}
@@ -0,0 +1,44 @@
1
+ /// <reference types="node" />
2
+ export interface ReconnectingEventSourceInit extends EventSourceInit {
3
+ max_retry_time?: number;
4
+ eventSourceClass?: typeof EventSource;
5
+ lastEventId?: string;
6
+ }
7
+ export declare class EventSourceNotAvailableError extends Error {
8
+ constructor();
9
+ }
10
+ declare type Listeners = {
11
+ [name: string]: ((this: EventSource, event: Event) => any)[];
12
+ };
13
+ export default class ReconnectingEventSource implements EventSource {
14
+ readonly _configuration: ReconnectingEventSourceInit | undefined;
15
+ readonly CONNECTING = 0;
16
+ readonly OPEN = 1;
17
+ readonly CLOSED = 2;
18
+ _eventSource: EventSource | null;
19
+ _lastEventId: string | null;
20
+ _timer: NodeJS.Timer | null;
21
+ _listeners: Listeners;
22
+ _onevent_wrapped: (this: EventSource, ev: Event) => any;
23
+ readyState: 0 | 1 | 2;
24
+ url: string;
25
+ withCredentials: boolean;
26
+ readonly max_retry_time: number;
27
+ eventSourceClass: typeof EventSource;
28
+ constructor(url: string | URL, configuration?: ReconnectingEventSourceInit);
29
+ dispatchEvent(event: Event): boolean;
30
+ _start(): void;
31
+ _onopen(event: Event): void;
32
+ _onerror(event: Event): void;
33
+ _onevent(event: Event): void;
34
+ onopen(event: Event): void;
35
+ onerror(event: Event): void;
36
+ onmessage(event: MessageEvent): void;
37
+ close(): void;
38
+ addEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
39
+ addEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | AddEventListenerOptions): void;
40
+ removeEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
41
+ removeEventListener(type: string, listener: (this: EventSource, event: MessageEvent<any>) => any, options?: boolean | EventListenerOptions): void;
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=reconnecting-eventsource.d.ts.map
@@ -1,6 +1,6 @@
1
1
  // MIT License:
2
2
  //
3
- // Copyright (C) 2017 Fanout, Inc.
3
+ // Copyright (C) 2022 Fanout, Inc.
4
4
  //
5
5
  // Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  // of this software and associated documentation files (the "Software"), to
@@ -19,185 +19,160 @@
19
19
  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
20
  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
21
  // IN THE SOFTWARE.
22
-
23
22
  export class EventSourceNotAvailableError extends Error {
24
23
  constructor() {
25
- super(
26
- 'EventSource not available.\n' +
27
- 'Consider loading an EventSource polyfill and making it available globally as EventSource, ' +
28
- 'or passing one in as eventSourceClass to the ReconnectingEventSource constructor.'
29
- );
24
+ super('EventSource not available.\n' +
25
+ 'Consider loading an EventSource polyfill and making it available globally as EventSource, ' +
26
+ 'or passing one in as eventSourceClass to the ReconnectingEventSource constructor.');
30
27
  }
31
28
  }
32
-
33
29
  export default class ReconnectingEventSource {
34
-
35
30
  constructor(url, configuration) {
36
- this._configuration = configuration != null ? Object.assign({}, configuration) : null;
37
-
31
+ this.CONNECTING = 0;
32
+ this.OPEN = 1;
33
+ this.CLOSED = 2;
34
+ this._configuration = configuration != null ? Object.assign({}, configuration) : undefined;
35
+ this.withCredentials = false;
38
36
  this._eventSource = null;
39
37
  this._lastEventId = null;
40
38
  this._timer = null;
41
39
  this._listeners = {};
42
-
43
- this.url = url;
44
- this.readyState = 0;
40
+ this.url = url.toString();
41
+ this.readyState = this.CONNECTING;
45
42
  this.max_retry_time = 3000;
46
43
  this.eventSourceClass = globalThis.EventSource;
47
-
48
44
  if (this._configuration != null) {
49
45
  if (this._configuration.lastEventId) {
50
46
  this._lastEventId = this._configuration.lastEventId;
51
47
  delete this._configuration['lastEventId'];
52
48
  }
53
-
54
49
  if (this._configuration.max_retry_time) {
55
50
  this.max_retry_time = this._configuration.max_retry_time;
56
51
  delete this._configuration['max_retry_time'];
57
52
  }
58
-
59
53
  if (this._configuration.eventSourceClass) {
60
54
  this.eventSourceClass = this._configuration.eventSourceClass;
61
55
  delete this._configuration['eventSourceClass'];
62
56
  }
63
57
  }
64
-
65
- if(this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {
58
+ if (this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {
66
59
  throw new EventSourceNotAvailableError();
67
60
  }
68
-
69
- this._onevent_wrapped = event => { this._onevent(event); };
70
-
61
+ this._onevent_wrapped = (event) => { this._onevent(event); };
71
62
  this._start();
72
63
  }
73
-
64
+ dispatchEvent(event) {
65
+ throw new Error("Method not implemented.");
66
+ }
74
67
  _start() {
75
68
  let url = this.url;
76
-
77
69
  if (this._lastEventId) {
78
70
  if (url.indexOf('?') === -1) {
79
71
  url += '?';
80
- } else {
72
+ }
73
+ else {
81
74
  url += '&';
82
75
  }
83
76
  url += 'lastEventId=' + encodeURIComponent(this._lastEventId);
84
77
  }
85
-
86
78
  this._eventSource = new this.eventSourceClass(url, this._configuration);
87
-
88
- this._eventSource.onopen = event => { this._onopen(event); };
89
- this._eventSource.onerror = event => { this._onerror(event); };
90
- this._eventSource.onmessage = event => { this.onmessage(event); };
91
-
79
+ this._eventSource.onopen = (event) => { this._onopen(event); };
80
+ this._eventSource.onerror = (event) => { this._onerror(event); };
81
+ this._eventSource.onmessage = (event) => { this.onmessage(event); };
92
82
  // apply listen types
93
83
  for (const type of Object.keys(this._listeners)) {
94
84
  this._eventSource.addEventListener(type, this._onevent_wrapped);
95
85
  }
96
86
  }
97
-
98
87
  _onopen(event) {
99
88
  if (this.readyState === 0) {
100
89
  this.readyState = 1;
101
90
  this.onopen(event);
102
91
  }
103
92
  }
104
-
105
93
  _onerror(event) {
106
94
  if (this.readyState === 1) {
107
95
  this.readyState = 0;
108
96
  this.onerror(event);
109
97
  }
110
-
111
98
  if (this._eventSource) {
112
- if(this._eventSource.readyState === 2) {
99
+ if (this._eventSource.readyState === 2) {
113
100
  // reconnect with new object
114
101
  this._eventSource.close();
115
102
  this._eventSource = null;
116
-
117
103
  // reconnect after random timeout < max_retry_time
118
104
  const timeout = Math.round(this.max_retry_time * Math.random());
119
105
  this._timer = setTimeout(() => this._start(), timeout);
120
106
  }
121
107
  }
122
108
  }
123
-
124
109
  _onevent(event) {
125
- if (event.lastEventId) {
110
+ if (event instanceof MessageEvent) {
126
111
  this._lastEventId = event.lastEventId;
127
112
  }
128
-
129
113
  const listenersForType = this._listeners[event.type];
130
114
  if (listenersForType != null) {
131
115
  // operate on a copy
132
116
  for (const listener of [...listenersForType]) {
133
- listener(event);
117
+ listener.call(this, event);
134
118
  }
135
119
  }
136
-
137
120
  if (event.type === 'message') {
138
121
  this.onmessage(event);
139
122
  }
140
123
  }
141
-
142
124
  onopen(event) {
143
125
  // may be overridden
144
126
  }
145
-
146
127
  onerror(event) {
147
128
  // may be overridden
148
129
  }
149
-
150
130
  onmessage(event) {
151
131
  // may be overridden
152
132
  }
153
-
154
133
  close() {
155
134
  if (this._timer) {
156
135
  clearTimeout(this._timer);
157
136
  this._timer = null;
158
137
  }
159
-
160
138
  if (this._eventSource) {
161
139
  this._eventSource.close();
162
140
  this._eventSource = null;
163
141
  }
164
-
165
142
  this.readyState = 2;
166
143
  }
167
-
168
- addEventListener(inType, callback) {
169
- const type = inType.toString();
170
-
144
+ addEventListener(type, listener, options) {
145
+ // We don't support the options arg at the moment
171
146
  if (!(type in this._listeners)) {
172
147
  this._listeners[type] = [];
173
- if (this._eventSource) {
148
+ if (this._eventSource != null) {
174
149
  this._eventSource.addEventListener(type, this._onevent_wrapped);
175
150
  }
176
151
  }
177
-
178
152
  const listenersForType = this._listeners[type];
179
- if (!listenersForType.includes(callback)) {
180
- this._listeners[type] = [...listenersForType, callback];
153
+ if (Array.isArray(listenersForType) && !listenersForType.includes(listener)) {
154
+ listenersForType.push(listener);
181
155
  }
182
156
  }
183
-
184
- removeEventListener(inType, callback) {
185
- const type = inType.toString();
186
-
187
- if (type in this._listeners) {
188
-
189
- const listenersForType = this._listeners[type];
190
-
191
- const updatedListenersForType = listenersForType.filter(l => l !== callback);
192
-
193
- if (updatedListenersForType.length > 0) {
194
- this._listeners[type] = updatedListenersForType;
195
- } else {
157
+ removeEventListener(type, listener, options) {
158
+ // We don't support the options arg at the moment
159
+ const listenersForType = this._listeners[type];
160
+ if (listenersForType != null) {
161
+ // eslint-disable-next-line no-constant-condition
162
+ while (true) {
163
+ const index = listenersForType.indexOf(listener);
164
+ if (index === -1) {
165
+ break;
166
+ }
167
+ listenersForType.splice(index, 1);
168
+ }
169
+ if (listenersForType.length <= 0) {
196
170
  delete this._listeners[type];
197
- if (this._eventSource) {
171
+ if (this._eventSource != null) {
198
172
  this._eventSource.removeEventListener(type, this._onevent_wrapped);
199
173
  }
200
174
  }
201
175
  }
202
176
  }
203
177
  }
178
+ //# sourceMappingURL=reconnecting-eventsource.js.map