reconnecting-eventsource 1.2.0 → 1.5.0

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)
@@ -48,11 +48,12 @@ Like the [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventS
48
48
  // the maximum time to wait before attempting to reconnect in ms, default `3000`
49
49
  // note: wait time is randomised to prevent all clients from attempting to reconnect simultaneously
50
50
  max_retry_time: 3000,
51
- }
52
51
 
52
+ // underlying EventSource class, default `EventSource`
53
+ eventSourceClass: EventSource,
54
+ }
53
55
  ```
54
56
 
55
-
56
57
  ## Building from source
57
58
 
58
59
  If you wish to build this project, check out this repository and modify the source files in `src/`. Then, run the following command:
@@ -0,0 +1,42 @@
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
+ [K in keyof EventSourceEventMap]: ((this: EventSource, ev: EventSourceEventMap[K]) => 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, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
39
+ removeEventListener<K extends keyof EventSourceEventMap>(type: K, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=reconnecting-eventsource.d.ts.map
@@ -0,0 +1,248 @@
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
+ open: [],
96
+ error: [],
97
+ message: [],
98
+ };
99
+ this.url = url.toString();
100
+ this.readyState = this.CONNECTING;
101
+ this.max_retry_time = 3000;
102
+ this.eventSourceClass = globalThis.EventSource;
103
+ if (this._configuration != null) {
104
+ if (this._configuration.lastEventId) {
105
+ this._lastEventId = this._configuration.lastEventId;
106
+ delete this._configuration['lastEventId'];
107
+ }
108
+ if (this._configuration.max_retry_time) {
109
+ this.max_retry_time = this._configuration.max_retry_time;
110
+ delete this._configuration['max_retry_time'];
111
+ }
112
+ if (this._configuration.eventSourceClass) {
113
+ this.eventSourceClass = this._configuration.eventSourceClass;
114
+ delete this._configuration['eventSourceClass'];
115
+ }
116
+ }
117
+ if (this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {
118
+ throw new EventSourceNotAvailableError();
119
+ }
120
+ this._onevent_wrapped = function (event) { _this._onevent(event); };
121
+ this._start();
122
+ }
123
+ ReconnectingEventSource.prototype.dispatchEvent = function (event) {
124
+ throw new Error("Method not implemented.");
125
+ };
126
+ ReconnectingEventSource.prototype._start = function () {
127
+ var e_1, _a;
128
+ var _this = this;
129
+ var url = this.url;
130
+ if (this._lastEventId) {
131
+ if (url.indexOf('?') === -1) {
132
+ url += '?';
133
+ }
134
+ else {
135
+ url += '&';
136
+ }
137
+ url += 'lastEventId=' + encodeURIComponent(this._lastEventId);
138
+ }
139
+ this._eventSource = new this.eventSourceClass(url, this._configuration);
140
+ this._eventSource.onopen = function (event) { _this._onopen(event); };
141
+ this._eventSource.onerror = function (event) { _this._onerror(event); };
142
+ this._eventSource.onmessage = function (event) { _this.onmessage(event); };
143
+ try {
144
+ // apply listen types
145
+ for (var _b = __values(Object.keys(this._listeners)), _c = _b.next(); !_c.done; _c = _b.next()) {
146
+ var type = _c.value;
147
+ this._eventSource.addEventListener(type, this._onevent_wrapped);
148
+ }
149
+ }
150
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
151
+ finally {
152
+ try {
153
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
154
+ }
155
+ finally { if (e_1) throw e_1.error; }
156
+ }
157
+ };
158
+ ReconnectingEventSource.prototype._onopen = function (event) {
159
+ if (this.readyState === 0) {
160
+ this.readyState = 1;
161
+ this.onopen(event);
162
+ }
163
+ };
164
+ ReconnectingEventSource.prototype._onerror = function (event) {
165
+ var _this = this;
166
+ if (this.readyState === 1) {
167
+ this.readyState = 0;
168
+ this.onerror(event);
169
+ }
170
+ if (this._eventSource) {
171
+ if (this._eventSource.readyState === 2) {
172
+ // reconnect with new object
173
+ this._eventSource.close();
174
+ this._eventSource = null;
175
+ // reconnect after random timeout < max_retry_time
176
+ var timeout = Math.round(this.max_retry_time * Math.random());
177
+ this._timer = setTimeout(function () { return _this._start(); }, timeout);
178
+ }
179
+ }
180
+ };
181
+ ReconnectingEventSource.prototype._onevent = function (event) {
182
+ var e_2, _a;
183
+ if (event instanceof MessageEvent) {
184
+ this._lastEventId = event.lastEventId;
185
+ }
186
+ var listenersForType = this._listeners[event.type];
187
+ if (listenersForType != null) {
188
+ try {
189
+ // operate on a copy
190
+ for (var _b = __values(__spreadArray([], __read(listenersForType), false)), _c = _b.next(); !_c.done; _c = _b.next()) {
191
+ var listener = _c.value;
192
+ listener.call(this, event);
193
+ }
194
+ }
195
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
196
+ finally {
197
+ try {
198
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
199
+ }
200
+ finally { if (e_2) throw e_2.error; }
201
+ }
202
+ }
203
+ if (event.type === 'message') {
204
+ this.onmessage(event);
205
+ }
206
+ };
207
+ ReconnectingEventSource.prototype.onopen = function (event) {
208
+ // may be overridden
209
+ };
210
+ ReconnectingEventSource.prototype.onerror = function (event) {
211
+ // may be overridden
212
+ };
213
+ ReconnectingEventSource.prototype.onmessage = function (event) {
214
+ // may be overridden
215
+ };
216
+ ReconnectingEventSource.prototype.close = function () {
217
+ if (this._timer) {
218
+ clearTimeout(this._timer);
219
+ this._timer = null;
220
+ }
221
+ if (this._eventSource) {
222
+ this._eventSource.close();
223
+ this._eventSource = null;
224
+ }
225
+ this.readyState = 2;
226
+ };
227
+ ReconnectingEventSource.prototype.addEventListener = function (type, callback, options) {
228
+ // We don't support options at the moment
229
+ if (this._listeners[type] == null) {
230
+ this._listeners[type] = [];
231
+ if (this._eventSource != null) {
232
+ this._eventSource.addEventListener(type, this._onevent_wrapped);
233
+ }
234
+ }
235
+ var listenersForType = this._listeners[type];
236
+ if (!listenersForType.includes(callback)) {
237
+ this._listeners[type] = __spreadArray(__spreadArray([], __read(listenersForType), false), [callback], false);
238
+ }
239
+ };
240
+ ReconnectingEventSource.prototype.removeEventListener = function (type, callback, options) {
241
+ // We don't support options at the moment
242
+ var listenersForType = this._listeners[type];
243
+ this._listeners[type] = listenersForType.filter(function (l) { return l !== callback; });
244
+ };
245
+ return ReconnectingEventSource;
246
+ }());
247
+ export default ReconnectingEventSource;
248
+ //# sourceMappingURL=reconnecting-eventsource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconnecting-eventsource.js","sourceRoot":"","sources":["../../src/reconnecting-eventsource.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,EAAE;AACF,kCAAkC;AAClC,EAAE;AACF,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,8EAA8E;AAC9E,6EAA6E;AAC7E,2DAA2D;AAC3D,EAAE;AACF,6EAA6E;AAC7E,sDAAsD;AACtD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,8EAA8E;AAC9E,yEAAyE;AACzE,0EAA0E;AAC1E,+EAA+E;AAC/E,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAenB;IAAkD,gDAAK;IACnD;eACI,kBACE,8BAA8B;YAC9B,4FAA4F;YAC5F,mFAAmF,CACpF;IACL,CAAC;IACL,mCAAC;AAAD,CAAC,AARD,CAAkD,KAAK,GAQtD;;AAMD;IAoBI,iCAAY,GAAiB,EAAE,aAA2C;QAA1E,iBA0CC;QA3DQ,eAAU,GAAG,CAAC,CAAC;QACf,SAAI,GAAG,CAAC,CAAC;QACT,WAAM,GAAG,CAAC,CAAC;QAgBhB,IAAI,CAAC,cAAc,GAAG,aAAa,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3F,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAE7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG;YACd,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;SACd,CAAC;QAEF,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC1B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,WAAW,CAAC;QAE/C,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,EAAE;YAC7B,IAAI,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE;gBACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC;gBACpD,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;aAC7C;YAED,IAAI,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE;gBACpC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC;gBACzD,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;aAChD;YAED,IAAI,IAAI,CAAC,cAAc,CAAC,gBAAgB,EAAE;gBACtC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC;gBAC7D,OAAO,IAAI,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;aAClD;SACJ;QAED,IAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,gBAAgB,KAAK,UAAU,EAAE;YAC7E,MAAM,IAAI,4BAA4B,EAAE,CAAC;SAC5C;QAED,IAAI,CAAC,gBAAgB,GAAG,UAAC,KAAK,IAAO,KAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC;IAED,+CAAa,GAAb,UAAc,KAAY;QACtB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC/C,CAAC;IAED,wCAAM,GAAN;;QAAA,iBAsBC;QArBG,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QAEnB,IAAI,IAAI,CAAC,YAAY,EAAE;YACnB,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;gBACzB,GAAG,IAAI,GAAG,CAAC;aACd;iBAAM;gBACH,GAAG,IAAI,GAAG,CAAC;aACd;YACD,GAAG,IAAI,cAAc,GAAG,kBAAkB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;SACjE;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QAExE,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,UAAC,KAAK,IAAO,KAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,YAAY,CAAC,OAAO,GAAG,UAAC,KAAK,IAAO,KAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,UAAC,KAAK,IAAO,KAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;;YAEpE,qBAAqB;YACrB,KAAmB,IAAA,KAAA,SAAA,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA,gBAAA,4BAAE;gBAA5C,IAAM,IAAI,WAAA;gBACX,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;aACnE;;;;;;;;;IACL,CAAC;IAED,yCAAO,GAAP,UAAQ,KAAY;QAChB,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE;YACvB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACtB;IACL,CAAC;IAED,0CAAQ,GAAR,UAAS,KAAY;QAArB,iBAiBC;QAhBG,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,EAAE;YACvB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;SACvB;QAED,IAAI,IAAI,CAAC,YAAY,EAAE;YACnB,IAAG,IAAI,CAAC,YAAY,CAAC,UAAU,KAAK,CAAC,EAAE;gBACnC,4BAA4B;gBAC5B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;gBAC1B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;gBAEzB,kDAAkD;gBAClD,IAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAChE,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,cAAM,OAAA,KAAI,CAAC,MAAM,EAAE,EAAb,CAAa,EAAE,OAAO,CAAC,CAAC;aAC1D;SACJ;IACL,CAAC;IAED,0CAAQ,GAAR,UAAS,KAAY;;QACjB,IAAI,KAAK,YAAY,YAAY,EAAE;YAC/B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC;SACzC;QAED,IAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAoC,CAA6C,CAAC;QACjI,IAAI,gBAAgB,IAAI,IAAI,EAAE;;gBAC1B,oBAAoB;gBACpB,KAAuB,IAAA,KAAA,kCAAI,gBAAgB,UAAC,gBAAA,4BAAE;oBAAzC,IAAM,QAAQ,WAAA;oBACf,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;iBAC9B;;;;;;;;;SACJ;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE;YAC1B,IAAI,CAAC,SAAS,CAAC,KAAqB,CAAC,CAAC;SACzC;IACL,CAAC;IAED,wCAAM,GAAN,UAAO,KAAY;QACf,oBAAoB;IACxB,CAAC;IAED,yCAAO,GAAP,UAAQ,KAAY;QAChB,oBAAoB;IACxB,CAAC;IAED,2CAAS,GAAT,UAAU,KAAmB;QACzB,oBAAoB;IACxB,CAAC;IAED,uCAAK,GAAL;QACI,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;SACtB;QAED,IAAI,IAAI,CAAC,YAAY,EAAE;YACnB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;SAC5B;QAED,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,kDAAgB,GAAhB,UAAsD,IAAO,EAAE,QAAgE,EAAE,OAA2C;QACxK,yCAAyC;QAEzC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE;YAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,EAAE;gBAC3B,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;aACnE;SACJ;QAED,IAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;YACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,uCAAI,gBAAgB,YAAE,QAAQ,SAA2B,CAAC;SACrF;IACL,CAAC;IAED,qDAAmB,GAAnB,UAAyD,IAAO,EAAE,QAAgE,EAAE,OAA2C;QAC3K,yCAAyC;QAEzC,IAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,KAAK,QAAQ,EAAd,CAAc,CAA2B,CAAC;IACnG,CAAC;IACL,8BAAC;AAAD,CAAC,AAxLD,IAwLC","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 Listeners = {\n [K in keyof EventSourceEventMap]: ((this: EventSource, ev: EventSourceEventMap[K]) => 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 open: [],\n error: [],\n message: [],\n };\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 as keyof typeof this._listeners] as ((this:EventSource, ev: Event) => any)[];\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, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions) {\n // We don't support options at the moment\n\n if (this._listeners[type] == null) {\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];\n if (!listenersForType.includes(callback)) {\n this._listeners[type] = [...listenersForType, callback] as Listeners[typeof type];\n }\n }\n\n removeEventListener<K extends keyof EventSourceEventMap>(type: K, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions) {\n // We don't support options at the moment\n\n const listenersForType = this._listeners[type];\n this._listeners[type] = listenersForType.filter(l => l !== callback) as Listeners[typeof type];\n }\n}\n"]}
@@ -0,0 +1,42 @@
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
+ [K in keyof EventSourceEventMap]: ((this: EventSource, ev: EventSourceEventMap[K]) => 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, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
39
+ removeEventListener<K extends keyof EventSourceEventMap>(type: K, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
40
+ }
41
+ export {};
42
+ //# 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,165 +19,149 @@
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
-
22
+ export class EventSourceNotAvailableError extends Error {
23
+ constructor() {
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.');
27
+ }
28
+ }
23
29
  export default class ReconnectingEventSource {
24
-
25
30
  constructor(url, configuration) {
26
- this._configuration = configuration != null ? Object.assign({}, configuration) : null;
27
-
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;
28
36
  this._eventSource = null;
29
37
  this._lastEventId = null;
30
38
  this._timer = null;
31
- this._listeners = {};
32
-
33
- this.url = url;
34
- this.readyState = 0;
39
+ this._listeners = {
40
+ open: [],
41
+ error: [],
42
+ message: [],
43
+ };
44
+ this.url = url.toString();
45
+ this.readyState = this.CONNECTING;
35
46
  this.max_retry_time = 3000;
36
-
47
+ this.eventSourceClass = globalThis.EventSource;
37
48
  if (this._configuration != null) {
38
49
  if (this._configuration.lastEventId) {
39
50
  this._lastEventId = this._configuration.lastEventId;
40
51
  delete this._configuration['lastEventId'];
41
52
  }
42
-
43
53
  if (this._configuration.max_retry_time) {
44
54
  this.max_retry_time = this._configuration.max_retry_time;
45
55
  delete this._configuration['max_retry_time'];
46
56
  }
57
+ if (this._configuration.eventSourceClass) {
58
+ this.eventSourceClass = this._configuration.eventSourceClass;
59
+ delete this._configuration['eventSourceClass'];
60
+ }
47
61
  }
48
-
49
- this._onevent_wrapped = event => { this._onevent(event); };
50
-
62
+ if (this.eventSourceClass == null || typeof this.eventSourceClass !== 'function') {
63
+ throw new EventSourceNotAvailableError();
64
+ }
65
+ this._onevent_wrapped = (event) => { this._onevent(event); };
51
66
  this._start();
52
67
  }
53
-
68
+ dispatchEvent(event) {
69
+ throw new Error("Method not implemented.");
70
+ }
54
71
  _start() {
55
72
  let url = this.url;
56
-
57
73
  if (this._lastEventId) {
58
74
  if (url.indexOf('?') === -1) {
59
75
  url += '?';
60
- } else {
76
+ }
77
+ else {
61
78
  url += '&';
62
79
  }
63
80
  url += 'lastEventId=' + encodeURIComponent(this._lastEventId);
64
81
  }
65
-
66
- this._eventSource = new EventSource(url, this._configuration);
67
-
68
- this._eventSource.onopen = event => { this._onopen(event); };
69
- this._eventSource.onerror = event => { this._onerror(event); };
70
- this._eventSource.onmessage = event => { this.onmessage(event); };
71
-
82
+ this._eventSource = new this.eventSourceClass(url, this._configuration);
83
+ this._eventSource.onopen = (event) => { this._onopen(event); };
84
+ this._eventSource.onerror = (event) => { this._onerror(event); };
85
+ this._eventSource.onmessage = (event) => { this.onmessage(event); };
72
86
  // apply listen types
73
87
  for (const type of Object.keys(this._listeners)) {
74
88
  this._eventSource.addEventListener(type, this._onevent_wrapped);
75
89
  }
76
90
  }
77
-
78
91
  _onopen(event) {
79
92
  if (this.readyState === 0) {
80
93
  this.readyState = 1;
81
94
  this.onopen(event);
82
95
  }
83
96
  }
84
-
85
97
  _onerror(event) {
86
98
  if (this.readyState === 1) {
87
99
  this.readyState = 0;
88
100
  this.onerror(event);
89
101
  }
90
-
91
102
  if (this._eventSource) {
92
- if(this._eventSource.readyState === 2) {
103
+ if (this._eventSource.readyState === 2) {
93
104
  // reconnect with new object
94
105
  this._eventSource.close();
95
106
  this._eventSource = null;
96
-
97
107
  // reconnect after random timeout < max_retry_time
98
108
  const timeout = Math.round(this.max_retry_time * Math.random());
99
109
  this._timer = setTimeout(() => this._start(), timeout);
100
110
  }
101
111
  }
102
112
  }
103
-
104
113
  _onevent(event) {
105
- if (event.lastEventId) {
114
+ if (event instanceof MessageEvent) {
106
115
  this._lastEventId = event.lastEventId;
107
116
  }
108
-
109
117
  const listenersForType = this._listeners[event.type];
110
118
  if (listenersForType != null) {
111
119
  // operate on a copy
112
120
  for (const listener of [...listenersForType]) {
113
- listener(event);
121
+ listener.call(this, event);
114
122
  }
115
123
  }
116
-
117
124
  if (event.type === 'message') {
118
125
  this.onmessage(event);
119
126
  }
120
127
  }
121
-
122
128
  onopen(event) {
123
129
  // may be overridden
124
130
  }
125
-
126
131
  onerror(event) {
127
132
  // may be overridden
128
133
  }
129
-
130
134
  onmessage(event) {
131
135
  // may be overridden
132
136
  }
133
-
134
137
  close() {
135
138
  if (this._timer) {
136
139
  clearTimeout(this._timer);
137
140
  this._timer = null;
138
141
  }
139
-
140
142
  if (this._eventSource) {
141
143
  this._eventSource.close();
142
144
  this._eventSource = null;
143
145
  }
144
-
145
146
  this.readyState = 2;
146
147
  }
147
-
148
- addEventListener(inType, callback) {
149
- const type = inType.toString();
150
-
151
- if (!(type in this._listeners)) {
148
+ addEventListener(type, callback, options) {
149
+ // We don't support options at the moment
150
+ if (this._listeners[type] == null) {
152
151
  this._listeners[type] = [];
153
- if (this._eventSource) {
152
+ if (this._eventSource != null) {
154
153
  this._eventSource.addEventListener(type, this._onevent_wrapped);
155
154
  }
156
155
  }
157
-
158
156
  const listenersForType = this._listeners[type];
159
157
  if (!listenersForType.includes(callback)) {
160
158
  this._listeners[type] = [...listenersForType, callback];
161
159
  }
162
160
  }
163
-
164
- removeEventListener(inType, callback) {
165
- const type = inType.toString();
166
-
167
- if (type in this._listeners) {
168
-
169
- const listenersForType = this._listeners[type];
170
-
171
- const updatedListenersForType = listenersForType.filter(l => l !== callback);
172
-
173
- if (updatedListenersForType.length > 0) {
174
- this._listeners[type] = updatedListenersForType;
175
- } else {
176
- delete this._listeners[type];
177
- if (this._eventSource) {
178
- this._eventSource.removeEventListener(type, this._onevent_wrapped);
179
- }
180
- }
181
- }
161
+ removeEventListener(type, callback, options) {
162
+ // We don't support options at the moment
163
+ const listenersForType = this._listeners[type];
164
+ this._listeners[type] = listenersForType.filter(l => l !== callback);
182
165
  }
183
166
  }
167
+ //# 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 Listeners = {\n [K in keyof EventSourceEventMap]: ((this: EventSource, ev: EventSourceEventMap[K]) => 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 open: [],\n error: [],\n message: [],\n };\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 as keyof typeof this._listeners] as ((this:EventSource, ev: Event) => any)[];\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, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions) {\n // We don't support options at the moment\n\n if (this._listeners[type] == null) {\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];\n if (!listenersForType.includes(callback)) {\n this._listeners[type] = [...listenersForType, callback] as Listeners[typeof type];\n }\n }\n\n removeEventListener<K extends keyof EventSourceEventMap>(type: K, callback: (this: EventSource, ev: EventSourceEventMap[K]) => any, options?: boolean | AddEventListenerOptions) {\n // We don't support options at the moment\n\n const listenersForType = this._listeners[type];\n this._listeners[type] = listenersForType.filter(l => l !== callback) as Listeners[typeof type];\n }\n}\n"]}