-
Notifications
You must be signed in to change notification settings - Fork 0
/
cosmoz-sse.js
98 lines (89 loc) · 2.4 KB
/
cosmoz-sse.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// @license Copyright (C) 2020 Neovici AB - Apache 2 License
import { component, useEffect, useMemo, useState } from '@pionjs/pion';
const getJson = (input) => {
try {
return JSON.parse(input);
} catch (e) {
// eslint-disable-next-line no-console
console.error('cant parse JSON:', input);
}
},
SSEHandlers = {
text: (data) => data,
json: (data) => getJson(data),
},
// eslint-disable-next-line max-lines-per-function
CosmozSSE = function ({
events,
withCredentials = false,
handleAs = 'json',
url,
}) {
const isAttached = this.parentNode != null,
fireEvent = (type, eventInit) => {
this.dispatchEvent(new CustomEvent(type, eventInit));
},
configuration = useMemo(
() => ({
withCredentials,
}),
[withCredentials]
),
[source, setSource] = useState(null),
eventTypes = useMemo(() => (events && getJson(events)) || [], [events]),
onEvent = (event) => {
const handler = SSEHandlers[handleAs];
fireEvent(event.type, {
detail: {
data: handler(event.data),
},
});
},
unsubscribeFromEvents = () => {
if (source == null || !Array.isArray(eventTypes)) {
return;
}
eventTypes.forEach((eventType) =>
source.removeEventListener(eventType, onEvent)
);
};
useEffect(() => {
if (!isAttached || !url) {
return;
}
const source = new EventSource(url, configuration),
onMessage = (event) =>
fireEvent('message', { detail: { data: event.data } }),
onOpen = () => fireEvent('open'),
onError = (event) =>
fireEvent('error', { detail: { data: event.data } });
source.addEventListener('message', onMessage);
source.addEventListener('open', onOpen);
source.addEventListener('error', onError);
setSource(source);
return () => {
unsubscribeFromEvents();
source.close();
source.removeEventListener('message', onMessage);
source.removeEventListener('open', onOpen);
source.removeEventListener('error', onError);
setSource(null);
};
}, [isAttached, url, configuration]);
useEffect(() => {
if (!source || !Array.isArray(eventTypes)) {
return;
}
eventTypes.forEach((eventType) =>
source.addEventListener(eventType, onEvent)
);
return unsubscribeFromEvents;
}, [source, eventTypes]);
};
CosmozSSE.observedAttributes = [
'events',
'handle-as',
'url',
'with-credentials',
];
customElements.define('cosmoz-sse', component(CosmozSSE));