websocket-text-relay 1.1.2 → 1.1.4
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/.prettierignore +3 -0
- package/.prettierrc +4 -0
- package/changelog.md +11 -0
- package/docs/code-structure.md +1 -1
- package/eslint.config.js +28 -0
- package/package.json +15 -10
- package/{index.js → src/index.js} +25 -23
- package/src/language-server/JsonRpcInterface.js +59 -29
- package/src/language-server/JsonRpcInterface.test.js +102 -72
- package/src/language-server/LspReader.js +30 -20
- package/src/language-server/LspReader.test.js +147 -65
- package/src/language-server/LspWriter.js +5 -5
- package/src/language-server/LspWriter.test.js +31 -24
- package/src/ui/css/fonts.css +0 -1
- package/src/ui/css/main.css +7 -7
- package/src/ui/index.html +4 -4
- package/src/ui/js/components/ActivityTimeseriesGraph.js +83 -32
- package/src/ui/js/components/HeaderSummary.js +11 -5
- package/src/ui/js/components/ServerStatus.js +19 -7
- package/src/ui/js/components/SessionLabels.js +197 -49
- package/src/ui/js/components/SessionWedges.js +44 -24
- package/src/ui/js/components/StatusRing.js +20 -8
- package/src/ui/js/components/grids.js +14 -7
- package/src/ui/js/index.js +23 -19
- package/src/ui/js/main.js +53 -21
- package/src/ui/js/util/DependencyManager.js +5 -5
- package/src/ui/js/util/EventEmitter.js +11 -7
- package/src/ui/js/util/WebsocketClient.js +28 -22
- package/src/ui/js/util/constants.js +2 -2
- package/src/ui/js/util/drawing.js +58 -28
- package/src/websocket-interface/WebsocketClient.js +15 -15
- package/src/websocket-interface/WebsocketInterface.js +30 -22
- package/src/websocket-interface/WtrSession.js +49 -33
- package/src/websocket-interface/httpServer.js +24 -14
- package/src/websocket-interface/sessionManager.js +16 -13
- package/src/websocket-interface/util.js +1 -1
- package/src/websocket-interface/websocketApi.js +51 -34
- package/src/websocket-interface/websocketServer.js +9 -9
- package/start.js +1 -1
- package/.eslintrc +0 -29
package/src/ui/css/main.css
CHANGED
|
@@ -11,22 +11,21 @@
|
|
|
11
11
|
|
|
12
12
|
.color_palette {
|
|
13
13
|
--bg2: var(--color-navy-nightfall);
|
|
14
|
-
--accent-active: var(var(--color-golden-sunset))
|
|
14
|
+
--accent-active: var(var(--color-golden-sunset));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
.color_theme {
|
|
18
18
|
--main-background-color: var(--bg2);
|
|
19
19
|
--header-text-color: var(--color-ivory-daybreak);
|
|
20
20
|
--summary-value-text-color: hsl(from var(--header-text-color) h s l / 0.9);
|
|
21
|
-
--offline-color: oklch(from var(--color-golden-sunset) calc(l * .5) calc(c * .25) h);
|
|
22
|
-
--online-color: oklch(from var(--color-golden-sunset) calc(l * .
|
|
21
|
+
--offline-color: oklch(from var(--color-golden-sunset) calc(l * 0.5) calc(c * 0.25) h);
|
|
22
|
+
--online-color: oklch(from var(--color-golden-sunset) calc(l * 0.8) calc(c * 0.25) h);
|
|
23
23
|
--active-color: var(--color-golden-sunset);
|
|
24
|
-
--wedge-online-color: oklch(from var(--color-azure-afternoon) calc(l * .5) calc(c * .5) h);
|
|
24
|
+
--wedge-online-color: oklch(from var(--color-azure-afternoon) calc(l * 0.5) calc(c * 0.5) h);
|
|
25
25
|
--wedge-active-color: var(--color-azure-afternoon);
|
|
26
26
|
--timeseries-line-color: var(--color-tangerine-sunset);
|
|
27
27
|
--timeseries-label-color: #7f8186;
|
|
28
28
|
--timeseries-value-color: oklch(from var(--timeseries-label-color) calc(l * 1.2) c h);
|
|
29
|
-
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
body {
|
|
@@ -57,7 +56,7 @@ body {
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
.right_header {
|
|
60
|
-
text-anchor: end
|
|
59
|
+
text-anchor: end;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
.header_number {
|
|
@@ -80,7 +79,8 @@ body {
|
|
|
80
79
|
display: none;
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
.single_wedge_group.online,
|
|
82
|
+
.single_wedge_group.online,
|
|
83
|
+
.single_wedge_group.active {
|
|
84
84
|
display: inherit;
|
|
85
85
|
}
|
|
86
86
|
|
package/src/ui/index.html
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<meta charset="utf-8"
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
|
|
7
7
|
<title>WTR Status</title>
|
|
8
8
|
|
|
9
|
-
<link rel="stylesheet" href="css/fonts.css"
|
|
9
|
+
<link rel="stylesheet" href="css/fonts.css" />
|
|
10
10
|
<style id="main_style"></style>
|
|
11
11
|
<script type="module" src="js/index.js" defer></script>
|
|
12
12
|
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
const { exportDeps, drawSvgElement, drawCircle, drawLinearPath, coordsToPathData, drawText, drawToolTip } =
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
const { exportDeps, drawSvgElement, drawCircle, drawLinearPath, coordsToPathData, drawText, drawToolTip } =
|
|
2
|
+
window.__WTR__
|
|
3
|
+
|
|
4
|
+
const drawValueWithTooltip = ({ x, y, label, direction, parentNode }) => {
|
|
5
|
+
const tooltipWrapperGroup = drawSvgElement({
|
|
6
|
+
tag: "g",
|
|
7
|
+
className: "tooltip_wrapper_group",
|
|
8
|
+
parent: parentNode,
|
|
9
|
+
})
|
|
10
|
+
drawToolTip({ x: x, y: y - 0.0032, text: label, direction, parentNode: tooltipWrapperGroup })
|
|
11
|
+
return drawText({
|
|
12
|
+
x: x,
|
|
13
|
+
y: y,
|
|
14
|
+
dominantBaseline: "middle",
|
|
15
|
+
text: "0",
|
|
16
|
+
className: "timeseries_value",
|
|
17
|
+
parentNode: tooltipWrapperGroup,
|
|
18
|
+
})
|
|
7
19
|
}
|
|
8
20
|
|
|
9
21
|
const dataWindowSize = 16
|
|
@@ -14,7 +26,9 @@ const innerCircleClipPathId = "inner_circle_clip"
|
|
|
14
26
|
|
|
15
27
|
const createLinearScale = (domainMin, domainMax, rangeMin, rangeMax) => {
|
|
16
28
|
const domainSize = domainMax - domainMin
|
|
17
|
-
if (domainSize === 0) {
|
|
29
|
+
if (domainSize === 0) {
|
|
30
|
+
return () => rangeMin
|
|
31
|
+
}
|
|
18
32
|
const rangeSize = rangeMax - rangeMin
|
|
19
33
|
const ratio = rangeSize / domainSize
|
|
20
34
|
|
|
@@ -30,8 +44,10 @@ const createRandomDataWindow = () => {
|
|
|
30
44
|
for (let time = startTime; time < endTime; time += dataWindowInterval) {
|
|
31
45
|
// const value = Math.floor(Math.random() * 101)
|
|
32
46
|
const value = 0
|
|
33
|
-
if (value > maxValue) {
|
|
34
|
-
|
|
47
|
+
if (value > maxValue) {
|
|
48
|
+
maxValue = value
|
|
49
|
+
}
|
|
50
|
+
series.push({ time, value })
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
return series
|
|
@@ -41,25 +57,29 @@ const getSeriesWindowInfo = (series) => {
|
|
|
41
57
|
const startTime = series.at(1).time
|
|
42
58
|
const endTime = series.at(-1).time
|
|
43
59
|
let maxValue = 0
|
|
44
|
-
series.forEach(({value}) => {
|
|
45
|
-
if (value > maxValue) {
|
|
60
|
+
series.forEach(({ value }) => {
|
|
61
|
+
if (value > maxValue) {
|
|
62
|
+
maxValue = value
|
|
63
|
+
}
|
|
46
64
|
})
|
|
47
65
|
|
|
48
|
-
return {startTime, endTime, maxValue}
|
|
66
|
+
return { startTime, endTime, maxValue }
|
|
49
67
|
}
|
|
50
68
|
|
|
51
69
|
class ActivityTimeseriesGraph {
|
|
52
|
-
constructor
|
|
70
|
+
constructor({ innerRingRadius, parentNode }) {
|
|
53
71
|
this.innerRingRadius = innerRingRadius
|
|
54
72
|
this.parentNode = parentNode
|
|
55
73
|
this.parentNode.innerHTML = ""
|
|
56
74
|
this.dataWindow = window.activityDataWindow || createRandomDataWindow()
|
|
57
75
|
window.activityDataWindow = this.dataWindow
|
|
58
|
-
if (!window.currentActivityCount) {
|
|
76
|
+
if (!window.currentActivityCount) {
|
|
77
|
+
window.currentActivityCount = 0
|
|
78
|
+
}
|
|
59
79
|
this.draw()
|
|
60
80
|
}
|
|
61
81
|
|
|
62
|
-
draw
|
|
82
|
+
draw() {
|
|
63
83
|
const minX = -this.innerRingRadius
|
|
64
84
|
const maxX = this.innerRingRadius
|
|
65
85
|
const width = maxX - minX
|
|
@@ -67,26 +87,58 @@ class ActivityTimeseriesGraph {
|
|
|
67
87
|
const minY = -height / 2
|
|
68
88
|
const maxY = minY + height
|
|
69
89
|
|
|
70
|
-
const clipPath = drawSvgElement({
|
|
71
|
-
|
|
72
|
-
|
|
90
|
+
const clipPath = drawSvgElement({
|
|
91
|
+
tag: "clipPath",
|
|
92
|
+
attributes: { id: innerCircleClipPathId },
|
|
93
|
+
parent: this.parentNode,
|
|
94
|
+
})
|
|
95
|
+
drawCircle({ cx: 0, cy: 0, r: this.innerRingRadius - 0.005, parentNode: clipPath })
|
|
96
|
+
drawSvgElement({
|
|
97
|
+
tag: "rect",
|
|
98
|
+
attributes: {
|
|
99
|
+
"clip-path": `url(#${innerCircleClipPathId})`,
|
|
100
|
+
x: minX,
|
|
101
|
+
y: minY,
|
|
102
|
+
height,
|
|
103
|
+
width,
|
|
104
|
+
},
|
|
105
|
+
className: "timeseries_bg",
|
|
106
|
+
parent: this.parentNode,
|
|
107
|
+
})
|
|
73
108
|
|
|
74
109
|
const series = this.dataWindow
|
|
75
|
-
const {startTime, endTime, maxValue} = getSeriesWindowInfo(series)
|
|
76
|
-
|
|
77
|
-
const maxValueElement = drawValueWithTooltip({
|
|
78
|
-
|
|
110
|
+
const { startTime, endTime, maxValue } = getSeriesWindowInfo(series)
|
|
111
|
+
|
|
112
|
+
const maxValueElement = drawValueWithTooltip({
|
|
113
|
+
x: minX + width / 2,
|
|
114
|
+
y: minY - 0.08,
|
|
115
|
+
label: "Max updates in a 1 second window",
|
|
116
|
+
direction: "above",
|
|
117
|
+
parentNode: this.parentNode,
|
|
118
|
+
})
|
|
119
|
+
const currentValueElement = drawValueWithTooltip({
|
|
120
|
+
x: minX + width / 2,
|
|
121
|
+
y: maxY + 0.095,
|
|
122
|
+
label: "Updates in last full second",
|
|
123
|
+
parentNode: this.parentNode,
|
|
124
|
+
})
|
|
79
125
|
|
|
80
126
|
let valueScale = createLinearScale(0, maxValue, maxY, minY) // in svg, y increases as it goes down, so we need to flip max and min in the range
|
|
81
127
|
let timeScale = createLinearScale(startTime, endTime, minX, maxX)
|
|
82
128
|
|
|
83
|
-
const pathCoords = series.map(({time, value}) => {
|
|
129
|
+
const pathCoords = series.map(({ time, value }) => {
|
|
84
130
|
return [timeScale(time), valueScale(value)]
|
|
85
131
|
})
|
|
86
132
|
|
|
87
|
-
const graphPath = drawLinearPath({
|
|
133
|
+
const graphPath = drawLinearPath({
|
|
134
|
+
coords: pathCoords,
|
|
135
|
+
className: "timeseries_path",
|
|
136
|
+
parentNode: this.parentNode,
|
|
137
|
+
})
|
|
88
138
|
|
|
89
|
-
if (window.activityTimeout) {
|
|
139
|
+
if (window.activityTimeout) {
|
|
140
|
+
clearTimeout(window.activityTimeout)
|
|
141
|
+
}
|
|
90
142
|
const onTickUpdate = () => {
|
|
91
143
|
scheduleNextTick()
|
|
92
144
|
|
|
@@ -94,11 +146,11 @@ class ActivityTimeseriesGraph {
|
|
|
94
146
|
const prevEndTime = series.at(-1).time
|
|
95
147
|
const newTime = prevEndTime + dataWindowInterval
|
|
96
148
|
series.shift()
|
|
97
|
-
series.push({time: newTime, value: window.currentActivityCount})
|
|
149
|
+
series.push({ time: newTime, value: window.currentActivityCount })
|
|
98
150
|
currentValueElement.textContent = window.currentActivityCount
|
|
99
151
|
window.currentActivityCount = 0
|
|
100
152
|
|
|
101
|
-
const pathCoords = series.map(({time, value}) => {
|
|
153
|
+
const pathCoords = series.map(({ time, value }) => {
|
|
102
154
|
return [timeScale(time), valueScale(value)]
|
|
103
155
|
})
|
|
104
156
|
|
|
@@ -108,13 +160,13 @@ class ActivityTimeseriesGraph {
|
|
|
108
160
|
|
|
109
161
|
requestAnimationFrame(() => {
|
|
110
162
|
requestAnimationFrame(() => {
|
|
111
|
-
const {startTime, endTime, maxValue} = getSeriesWindowInfo(series)
|
|
163
|
+
const { startTime, endTime, maxValue } = getSeriesWindowInfo(series)
|
|
112
164
|
maxValueElement.textContent = maxValue
|
|
113
165
|
|
|
114
166
|
valueScale = createLinearScale(0, maxValue, maxY, minY) // in svg, y increases as it goes down, so we need to flip max and min in the range
|
|
115
167
|
timeScale = createLinearScale(startTime, endTime, minX, maxX)
|
|
116
168
|
|
|
117
|
-
const pathCoords = series.map(({time, value}) => {
|
|
169
|
+
const pathCoords = series.map(({ time, value }) => {
|
|
118
170
|
return [timeScale(time), valueScale(value)]
|
|
119
171
|
})
|
|
120
172
|
|
|
@@ -123,7 +175,6 @@ class ActivityTimeseriesGraph {
|
|
|
123
175
|
graphPath.setAttribute("d", pathData)
|
|
124
176
|
})
|
|
125
177
|
})
|
|
126
|
-
|
|
127
178
|
}
|
|
128
179
|
|
|
129
180
|
const scheduleNextTick = () => {
|
|
@@ -135,9 +186,9 @@ class ActivityTimeseriesGraph {
|
|
|
135
186
|
scheduleNextTick()
|
|
136
187
|
}
|
|
137
188
|
|
|
138
|
-
triggerActivity
|
|
189
|
+
triggerActivity() {
|
|
139
190
|
window.currentActivityCount++
|
|
140
191
|
}
|
|
141
192
|
}
|
|
142
193
|
|
|
143
|
-
exportDeps({ActivityTimeseriesGraph})
|
|
194
|
+
exportDeps({ ActivityTimeseriesGraph })
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
const { exportDeps, drawText } = window.__WTR__
|
|
2
2
|
|
|
3
3
|
class HeaderSummary {
|
|
4
|
-
constructor
|
|
4
|
+
constructor({ parentNode }) {
|
|
5
5
|
this.parentNode = parentNode
|
|
6
6
|
this.draw()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
draw
|
|
9
|
+
draw() {
|
|
10
10
|
this.parentNode.innerHTML = ""
|
|
11
|
-
drawText({x:
|
|
12
|
-
drawText({
|
|
11
|
+
drawText({ x: -0.86, y: -0.73, text: "editors", parentNode: this.parentNode })
|
|
12
|
+
drawText({
|
|
13
|
+
x: 0.86,
|
|
14
|
+
y: -0.73,
|
|
15
|
+
text: "clients",
|
|
16
|
+
className: "right_header",
|
|
17
|
+
parentNode: this.parentNode,
|
|
18
|
+
})
|
|
13
19
|
}
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
exportDeps({HeaderSummary})
|
|
22
|
+
exportDeps({ HeaderSummary })
|
|
@@ -4,19 +4,31 @@ const valueTextClass = "server_status_value"
|
|
|
4
4
|
const offlineTextClass = "server_status_offline"
|
|
5
5
|
|
|
6
6
|
class ServerStatus {
|
|
7
|
-
constructor
|
|
7
|
+
constructor({ parentNode }) {
|
|
8
8
|
this.parentNode = parentNode
|
|
9
9
|
this.draw()
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
draw
|
|
12
|
+
draw() {
|
|
13
13
|
this.parentNode.innerHTML = ""
|
|
14
|
-
drawText({
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
drawText({
|
|
15
|
+
x: 0,
|
|
16
|
+
y: 0.85,
|
|
17
|
+
text: "WS Server PID",
|
|
18
|
+
className: "server_status_label",
|
|
19
|
+
parentNode: this.parentNode,
|
|
20
|
+
})
|
|
21
|
+
this.valueElement = drawText({ x: 0, y: 0.748, text: "138324", parentNode: this.parentNode })
|
|
22
|
+
this.offlineElement = drawText({
|
|
23
|
+
x: 0,
|
|
24
|
+
y: 0.748,
|
|
25
|
+
text: "OFFLINE",
|
|
26
|
+
className: offlineTextClass,
|
|
27
|
+
parentNode: this.parentNode,
|
|
28
|
+
})
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
update
|
|
31
|
+
update(pid) {
|
|
20
32
|
if (pid == null) {
|
|
21
33
|
this.valueElement.classList.remove(valueTextClass)
|
|
22
34
|
this.offlineElement.classList.add(offlineTextClass)
|
|
@@ -28,4 +40,4 @@ class ServerStatus {
|
|
|
28
40
|
}
|
|
29
41
|
}
|
|
30
42
|
|
|
31
|
-
exportDeps({ServerStatus})
|
|
43
|
+
exportDeps({ ServerStatus })
|