mirror of
https://github.com/thomasnordquist/MQTT-Explorer.git
synced 2026-09-12 09:35:01 +00:00
Compare commits
45
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69897b4345 | ||
|
|
a63b12b266 | ||
|
|
a8ff4adde7 | ||
|
|
3b8418ccfd | ||
|
|
b51b3065b0 | ||
|
|
1f0c6771e5 | ||
|
|
67277b4652 | ||
|
|
b0e30a896f | ||
|
|
93010dc06e | ||
|
|
302b8f3c21 | ||
|
|
62d087bb0e | ||
|
|
f25cab4682 | ||
|
|
d1de0770f2 | ||
|
|
2a3f481a24 | ||
|
|
ed492ccbf4 | ||
|
|
ea7535b250 | ||
|
|
b17b54490e | ||
|
|
72400af679 | ||
|
|
f8f1ddfebb | ||
|
|
6e4d08e4b5 | ||
|
|
5da8fe0f90 | ||
|
|
df9eda4866 | ||
|
|
6b030ab5ee | ||
|
|
e1493db7c8 | ||
|
|
205ea00c41 | ||
|
|
d428428a6e | ||
|
|
24e9c4cd22 | ||
|
|
d253c6c764 | ||
|
|
13b8f8d5da | ||
|
|
e769ddece4 | ||
|
|
64e807beef | ||
|
|
531af31490 | ||
|
|
e708e1d0c7 | ||
|
|
8fcf8b2478 | ||
|
|
4fdd5b2063 | ||
|
|
e4add31793 | ||
|
|
0cab2169c2 | ||
|
|
86f5b94852 | ||
|
|
f60449c253 | ||
|
|
c1c8b9aa61 | ||
|
|
dcf692d193 | ||
|
|
7f757b9f8a | ||
|
|
23b46cd432 | ||
|
|
68ef9ac913 | ||
|
|
9cdfa2de7b |
@@ -66,9 +66,8 @@ node dist/src/spec/webdriverio.js
|
||||
## Write docs
|
||||
|
||||
```
|
||||
git clone https://github.com/thomasnordquist/MQTT-Explorer.git mqtt-explorer-pages
|
||||
git clone --single-branch -b gh-pages https://github.com/thomasnordquist/MQTT-Explorer.git mqtt-explorer-pages
|
||||
cd mqtt-explorer-pages
|
||||
git checkout gh-pages
|
||||
bundle install
|
||||
bundle exec jekyll serve --incremental
|
||||
```
|
||||
|
||||
+168
-152
@@ -1,181 +1,197 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
|
||||
<title>MQTT Explorer</title>
|
||||
<script src="./bugtracking.bundle.js"></script>
|
||||
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
|
||||
<title>MQTT Explorer</title>
|
||||
<script src="./bugtracking.bundle.js"></script>
|
||||
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[tabindex] {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@keyframes updateDark {
|
||||
0% {
|
||||
background-color: none;
|
||||
}
|
||||
|
||||
[tabindex] {
|
||||
outline: none;
|
||||
25% {
|
||||
background-color: #595585;
|
||||
}
|
||||
|
||||
@keyframes updateDark {
|
||||
0% {
|
||||
background-color: none;
|
||||
}
|
||||
25% {
|
||||
background-color: #595585;
|
||||
}
|
||||
50% {
|
||||
background-color: #595585;
|
||||
}
|
||||
100% {
|
||||
background-color: none;
|
||||
}
|
||||
50% {
|
||||
background-color: #595585;
|
||||
}
|
||||
|
||||
@keyframes updateLight {
|
||||
0% {
|
||||
background-color: none;
|
||||
color: inherit;
|
||||
}
|
||||
25% {
|
||||
background-color: #c0c8c0;
|
||||
}
|
||||
50% {
|
||||
background-color: #c0c8c0;
|
||||
}
|
||||
100% {
|
||||
background-color: none;
|
||||
color: inherit;
|
||||
}
|
||||
100% {
|
||||
background-color: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes updateLight {
|
||||
0% {
|
||||
background-color: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
25% {
|
||||
background-color: #c0c8c0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
50% {
|
||||
background-color: #c0c8c0;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(60, 60, 60, 0.5);
|
||||
background-color: rgba(140, 140, 140, 0.1);
|
||||
100% {
|
||||
background-color: none;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(140, 140, 140, 0.8);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.Resizer {
|
||||
background: rgba(200, 200, 200, 0);
|
||||
z-index: 10;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.Resizer:hover {
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.Resizer.horizontal {
|
||||
height: 10px;
|
||||
margin: -10px 0 0 0;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 6px rgba(60, 60, 60, 0.5);
|
||||
background-color: rgba(140, 140, 140, 0.1);
|
||||
}
|
||||
|
||||
.Resizer.horizontal::before {
|
||||
content: '•••';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: -22px;
|
||||
color: #aaa;
|
||||
opacity: 1;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(140, 140, 140, 0.8);
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.Resizer {
|
||||
background: rgba(200, 200, 200, 0);
|
||||
z-index: 10;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-background-clip: padding;
|
||||
-webkit-background-clip: padding;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.Resizer.horizontal:hover {
|
||||
border-top: 5px solid rgba(120, 120, 120, 0.3);
|
||||
border-bottom: 5px solid rgba(120, 120, 120, 0.3);
|
||||
}
|
||||
.Resizer:hover {
|
||||
-webkit-transition: all 0.3s ease-out;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.Resizer.vertical {
|
||||
width: 2px;
|
||||
margin: 0px -8px 0px 0px;
|
||||
border-left: 0px solid rgba(128, 128, 128, 0);
|
||||
border-right: 8px solid rgba(128, 128, 128, 0);
|
||||
cursor: col-resize;
|
||||
}
|
||||
.Resizer.horizontal {
|
||||
height: 10px;
|
||||
margin: -10px 0 0 0;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.Resizer.vertical::before {
|
||||
content: '•••';
|
||||
margin-left: -11px;
|
||||
height: 3em;
|
||||
margin-top: calc(50vh - 32px);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
opacity: 1;
|
||||
writing-mode: vertical-lr;
|
||||
text-orientation: sideways;
|
||||
}
|
||||
.Resizer.horizontal::before {
|
||||
content: '•••';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: -22px;
|
||||
color: #aaa;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.Resizer.vertical:hover {
|
||||
border-left: 0px solid rgba(130, 130, 130, 0.3);
|
||||
border-right: 8px solid rgba(140, 140, 140, 0.3);
|
||||
}
|
||||
.Resizer.horizontal:hover {
|
||||
border-top: 5px solid rgba(120, 120, 120, 0.3);
|
||||
border-bottom: 5px solid rgba(120, 120, 120, 0.3);
|
||||
}
|
||||
|
||||
.Resizer.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.Resizer.disabled:hover {
|
||||
border-color: transparent;
|
||||
}
|
||||
.Resizer.vertical {
|
||||
width: 2px;
|
||||
margin: 0px -8px 0px 0px;
|
||||
border-left: 0px solid rgba(128, 128, 128, 0);
|
||||
border-right: 8px solid rgba(128, 128, 128, 0);
|
||||
cursor: col-resize;
|
||||
}
|
||||
|
||||
.example-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
.example-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
.example-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
.example-exit-active {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" style="font: -webkit-control;"></div>
|
||||
<script>
|
||||
function loadScript(path) {
|
||||
var script = document.createElement('script')
|
||||
script.src = path
|
||||
document.head.appendChild(script)
|
||||
}
|
||||
.Resizer.vertical::before {
|
||||
content: '•••';
|
||||
margin-left: -11px;
|
||||
height: 3em;
|
||||
margin-top: calc(50vh - 32px);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
opacity: 1;
|
||||
writing-mode: vertical-lr;
|
||||
text-orientation: sideways;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', onLoad(), false)
|
||||
function onLoad() {
|
||||
// <% _.forEach(htmlWebpackPlugin.files.js, function(file) { %>loadScript("<%- file %>");<% }); %>
|
||||
// loadScript("<%= JSON.stringify(htmlWebpackPlugin) %>")
|
||||
}
|
||||
</script>
|
||||
<% _.forEach(htmlWebpackPlugin.files.js, function(file) { %>
|
||||
.Resizer.vertical:hover {
|
||||
border-left: 0px solid rgba(130, 130, 130, 0.3);
|
||||
border-right: 8px solid rgba(140, 140, 140, 0.3);
|
||||
}
|
||||
|
||||
.Resizer.disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.Resizer.disabled:hover {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.example-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.example-enter-active {
|
||||
opacity: 1;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
|
||||
.example-exit {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.example-exit-active {
|
||||
opacity: 0;
|
||||
transition: opacity 300ms ease-in;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
global = globalThis //<- this should be enough
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" style="font: -webkit-control;"></div>
|
||||
<script>
|
||||
function loadScript(path) {
|
||||
var script = document.createElement('script')
|
||||
script.src = path
|
||||
document.head.appendChild(script)
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', onLoad(), false)
|
||||
function onLoad() {
|
||||
// <% _.forEach(htmlWebpackPlugin.files.js, function(file) { %>loadScript("<%- file %>");<% }); %>
|
||||
// loadScript("<%= JSON.stringify(htmlWebpackPlugin) %>")
|
||||
}
|
||||
</script>
|
||||
<% _.forEach(htmlWebpackPlugin.files.js, function(file) { %>
|
||||
<script src="<%- file %>"></script>
|
||||
<% }); %>
|
||||
</body>
|
||||
</html>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+20
-19
@@ -4,30 +4,30 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "yarn rebuild && webpack --mode production",
|
||||
"build": "webpack --mode production",
|
||||
"dev": "node_modules/.bin/webpack-dev-server --mode development --progress",
|
||||
"rebuild": "cd node_modules/heapdump && node-gyp rebuild --target=7.1.1 --arch=x64 --dist-url=https://atom.io/download/electron || echo Could not build heapdump; cd -",
|
||||
"test": "cross-env TS_NODE_PROJECT=test/tsconfig.json yarn mochatest",
|
||||
"mochatest": "mocha --require ts-node/register src/**/*.spec.ts"
|
||||
},
|
||||
"engines": {
|
||||
"node": "19"
|
||||
},
|
||||
"author": "",
|
||||
"license": "CC-BY-ND-4.0",
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4",
|
||||
"@material-ui/core": "4.12",
|
||||
"@material-ui/icons": "^4",
|
||||
"@material-ui/lab": "^4.0.0-alpha",
|
||||
"@material-ui/styles": "^4",
|
||||
"@material-ui/styles": "4.11",
|
||||
"@types/react-transition-group": "^4",
|
||||
"ace-builds": "^1.4.11",
|
||||
"axios": "^0.19.0",
|
||||
"axios": "^0.26.0",
|
||||
"compare-versions": "^3.5.0",
|
||||
"copy-text-to-clipboard": "^2.1.0",
|
||||
"d3": "^5.9.7",
|
||||
"d3-shape": "^1.3.5",
|
||||
"diff": "^4.0.1",
|
||||
"dot-prop": "^5.0.0",
|
||||
"electron-telemetry": "git+https://github.com/thomasnordquist/electron-telemetry.git#dist",
|
||||
"file-loader": "6",
|
||||
"get-value": "^3.0.1",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"in-viewport": "^3.6.0",
|
||||
@@ -35,7 +35,6 @@
|
||||
"json-to-ast": "^2.1.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"moment": "^2.24.0",
|
||||
"moving-average": "^1.0.0",
|
||||
"number-abbreviate": "^2.0.0",
|
||||
"parse-duration": "^0.1.1",
|
||||
@@ -56,6 +55,7 @@
|
||||
"uuid": "7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "^7.17.2",
|
||||
"@types/d3": "^5.7.2",
|
||||
"@types/diff": "^4.0.1",
|
||||
"@types/get-value": "^3.0.1",
|
||||
@@ -69,24 +69,25 @@
|
||||
"@types/socket.io-client": "^1.4.32",
|
||||
"@types/uuid": "^7.0.2",
|
||||
"@types/vis": "^4.21.9",
|
||||
"awesome-typescript-loader": "^5.2.1",
|
||||
"chai": "^4.2.0",
|
||||
"cross-env": "^7.0.2",
|
||||
"css-loader": "^3.0.0",
|
||||
"hard-source-webpack-plugin": "^0.13.1",
|
||||
"heapdump": "^0.3.12",
|
||||
"html-webpack-plugin": "^4.0.0-beta.5",
|
||||
"mocha": "^7.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mocha": "^9.2.1",
|
||||
"moment": "^2.29.1",
|
||||
"node-loader": "^0.6.0",
|
||||
"source-map-loader": "^0.2.4",
|
||||
"style-loader": "^1",
|
||||
"typescript": "^3.6.3",
|
||||
"webpack": "^4.28.2",
|
||||
"webpack-bundle-analyzer": "^3.0.3",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.1.14"
|
||||
"ts-loader": "^9.2.6",
|
||||
"typescript": "^4.5.5",
|
||||
"webpack": "^5.69.1",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"electron": "^5.0.5"
|
||||
"electron": "^29"
|
||||
}
|
||||
}
|
||||
|
||||
+45
-53
@@ -60,63 +60,55 @@ export const saveCharts = () => async (dispatch: Dispatch<any>, getState: () =>
|
||||
}
|
||||
}
|
||||
|
||||
export const addChart = (chartParameters: ChartParameters) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
const chartExists = Boolean(
|
||||
getState()
|
||||
.charts.get('charts')
|
||||
.find(chart => chart.topic === chartParameters.topic && chart.dotPath === chartParameters.dotPath)
|
||||
)
|
||||
if (chartExists) {
|
||||
dispatch(showNotification('Already added'))
|
||||
return
|
||||
export const addChart =
|
||||
(chartParameters: ChartParameters) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const chartExists = Boolean(
|
||||
getState()
|
||||
.charts.get('charts')
|
||||
.find(chart => chart.topic === chartParameters.topic && chart.dotPath === chartParameters.dotPath)
|
||||
)
|
||||
if (chartExists) {
|
||||
dispatch(showNotification('Already added'))
|
||||
return
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ActionTypes.CHARTS_ADD,
|
||||
chart: chartParameters,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
dispatch(showNotification('Added to chart panel'))
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: ActionTypes.CHARTS_ADD,
|
||||
chart: chartParameters,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
dispatch(showNotification('Added to chart panel'))
|
||||
}
|
||||
export const updateChart =
|
||||
(chartParameters: ChartParameters) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch({
|
||||
type: ActionTypes.CHARTS_UPDATE,
|
||||
topic: chartParameters.topic,
|
||||
dotPath: chartParameters.dotPath,
|
||||
parameters: chartParameters,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
|
||||
export const updateChart = (chartParameters: ChartParameters) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({
|
||||
type: ActionTypes.CHARTS_UPDATE,
|
||||
topic: chartParameters.topic,
|
||||
dotPath: chartParameters.dotPath,
|
||||
parameters: chartParameters,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
export const removeChart =
|
||||
(chartParameters: ChartParameters) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch({
|
||||
chart: chartParameters,
|
||||
type: ActionTypes.CHARTS_REMOVE,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
|
||||
export const removeChart = (chartParameters: ChartParameters) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({
|
||||
chart: chartParameters,
|
||||
type: ActionTypes.CHARTS_REMOVE,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
|
||||
export const moveChartUp = (parameters: { topic: string; dotPath?: string }) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch({
|
||||
topic: parameters.topic,
|
||||
dotPath: parameters.dotPath,
|
||||
type: ActionTypes.CHARTS_MOVE_UP,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
export const moveChartUp =
|
||||
(parameters: { topic: string; dotPath?: string }) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch({
|
||||
topic: parameters.topic,
|
||||
dotPath: parameters.dotPath,
|
||||
type: ActionTypes.CHARTS_MOVE_UP,
|
||||
})
|
||||
dispatch(saveCharts())
|
||||
}
|
||||
|
||||
export const setCharts = (charts: Array<ChartParameters>): Action => {
|
||||
return {
|
||||
|
||||
@@ -11,31 +11,29 @@ import { showError } from './Global'
|
||||
import { TopicViewModel } from '../model/TopicViewModel'
|
||||
import { addMqttConnectionEvent, makeConnectionStateEvent, removeConnection, rendererEvents } from '../../../events'
|
||||
|
||||
export const connect = (options: MqttOptions, connectionId: string) => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch(connecting(connectionId))
|
||||
rendererEvents.emit(addMqttConnectionEvent, { options, id: connectionId })
|
||||
const event = makeConnectionStateEvent(connectionId)
|
||||
const host = url.parse(options.url).hostname
|
||||
export const connect =
|
||||
(options: MqttOptions, connectionId: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch(connecting(connectionId))
|
||||
rendererEvents.emit(addMqttConnectionEvent, { options, id: connectionId })
|
||||
const event = makeConnectionStateEvent(connectionId)
|
||||
const host = url.parse(options.url).hostname
|
||||
|
||||
rendererEvents.subscribe(event, dataSourceState => {
|
||||
if (dataSourceState.connected) {
|
||||
const didReconnect = Boolean(getState().connection.tree)
|
||||
if (!didReconnect) {
|
||||
const tree = new q.Tree<TopicViewModel>()
|
||||
tree.updateWithConnection(rendererEvents, connectionId)
|
||||
dispatch(showTree(tree))
|
||||
dispatch(connected(tree, host!))
|
||||
rendererEvents.subscribe(event, dataSourceState => {
|
||||
if (dataSourceState.connected) {
|
||||
const didReconnect = Boolean(getState().connection.tree)
|
||||
if (!didReconnect) {
|
||||
const tree = new q.Tree<TopicViewModel>()
|
||||
tree.updateWithConnection(rendererEvents, connectionId)
|
||||
dispatch(showTree(tree))
|
||||
dispatch(connected(tree, host!))
|
||||
}
|
||||
} else if (dataSourceState.error) {
|
||||
dispatch(showError(dataSourceState.error))
|
||||
dispatch(disconnect())
|
||||
}
|
||||
} else if (dataSourceState.error) {
|
||||
dispatch(showError(dataSourceState.error))
|
||||
dispatch(disconnect())
|
||||
}
|
||||
dispatch(updateHealth(dataSourceState))
|
||||
})
|
||||
}
|
||||
dispatch(updateHealth(dataSourceState))
|
||||
})
|
||||
}
|
||||
|
||||
const updateHealth = (dataSourceState: DataSourceState) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
let state
|
||||
|
||||
@@ -9,12 +9,13 @@ import {
|
||||
import { default as persistentStorage, StorageIdentifier } from '../utils/PersistentStorage'
|
||||
import { Dispatch } from 'redux'
|
||||
import { showError } from './Global'
|
||||
import { remote } from 'electron'
|
||||
import { promises as fsPromise } from 'fs'
|
||||
import * as path from 'path'
|
||||
import { ActionTypes, Action } from '../reducers/ConnectionManager'
|
||||
import { Subscription } from '../../../backend/src/DataSource/MqttSource'
|
||||
import { connectionsMigrator } from './migrations/Connection'
|
||||
import { rendererRpc } from '../../../events'
|
||||
import { makeOpenDialogRpc } from '../../../events/OpenDialogRequest'
|
||||
|
||||
export interface ConnectionDictionary {
|
||||
[s: string]: ConnectionOptions
|
||||
@@ -50,21 +51,19 @@ export const loadConnectionSettings = () => async (dispatch: Dispatch<any>, getS
|
||||
}
|
||||
|
||||
export type CertificateTypes = 'selfSignedCertificate' | 'clientCertificate' | 'clientKey'
|
||||
export const selectCertificate = (type: CertificateTypes, connectionId: string) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
try {
|
||||
const certificate = await openCertificate()
|
||||
dispatch(
|
||||
updateConnection(connectionId, {
|
||||
[type]: certificate,
|
||||
})
|
||||
)
|
||||
} catch (error) {
|
||||
dispatch(showError(error))
|
||||
export const selectCertificate =
|
||||
(type: CertificateTypes, connectionId: string) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
try {
|
||||
const certificate = await openCertificate()
|
||||
dispatch(
|
||||
updateConnection(connectionId, {
|
||||
[type]: certificate,
|
||||
})
|
||||
)
|
||||
} catch (error) {
|
||||
dispatch(showError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function openCertificate(): Promise<CertificateParameters> {
|
||||
const rejectReasons = {
|
||||
@@ -72,7 +71,7 @@ async function openCertificate(): Promise<CertificateParameters> {
|
||||
certificateSizeDoesNotMatch: 'Certificate size larger/smaller then expected.',
|
||||
}
|
||||
|
||||
const openDialogReturnValue = await remote.dialog.showOpenDialog(remote.getCurrentWindow(), {
|
||||
const openDialogReturnValue = await rendererRpc.call(makeOpenDialogRpc(), {
|
||||
properties: ['openFile'],
|
||||
securityScopedBookmarks: true,
|
||||
})
|
||||
@@ -83,7 +82,7 @@ async function openCertificate(): Promise<CertificateParameters> {
|
||||
}
|
||||
|
||||
const data = await fsPromise.readFile(selectedFile)
|
||||
if (data.length > 16_384 || data.length < 128) {
|
||||
if (data.length > 16_384 || data.length < 64) {
|
||||
throw rejectReasons.certificateSizeDoesNotMatch
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ActionTypes, ConfirmationRequest } from '../reducers/Global'
|
||||
import { Dispatch } from 'redux'
|
||||
|
||||
export const showError = (error?: string) => ({
|
||||
export const showError = (error?: string | unknown) => ({
|
||||
error,
|
||||
type: ActionTypes.showError,
|
||||
})
|
||||
|
||||
+17
-13
@@ -43,12 +43,14 @@ export const storeSettings = () => async (dispatch: Dispatch<any>, getState: ()
|
||||
}
|
||||
}
|
||||
|
||||
export const setAutoExpandLimit = (autoExpandLimit: number = 0) => (dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
autoExpandLimit,
|
||||
type: ActionTypes.SETTINGS_SET_AUTO_EXPAND_LIMIT,
|
||||
})
|
||||
}
|
||||
export const setAutoExpandLimit =
|
||||
(autoExpandLimit: number = 0) =>
|
||||
(dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
autoExpandLimit,
|
||||
type: ActionTypes.SETTINGS_SET_AUTO_EXPAND_LIMIT,
|
||||
})
|
||||
}
|
||||
|
||||
export const setTimeLocale = (timeLocale: string) => (dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
@@ -81,13 +83,15 @@ export const toggleHighlightTopicUpdates = () => (dispatch: Dispatch<any>) => {
|
||||
dispatch(storeSettings())
|
||||
}
|
||||
|
||||
export const setTopicOrder = (topicOrder: TopicOrder = TopicOrder.none) => (dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
topicOrder,
|
||||
type: ActionTypes.SETTINGS_SET_TOPIC_ORDER,
|
||||
})
|
||||
dispatch(storeSettings())
|
||||
}
|
||||
export const setTopicOrder =
|
||||
(topicOrder: TopicOrder = TopicOrder.none) =>
|
||||
(dispatch: Dispatch<any>) => {
|
||||
dispatch({
|
||||
topicOrder,
|
||||
type: ActionTypes.SETTINGS_SET_TOPIC_ORDER,
|
||||
})
|
||||
dispatch(storeSettings())
|
||||
}
|
||||
|
||||
export const filterTopics = (filterStr: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const { tree } = getState().connection
|
||||
|
||||
+21
-22
@@ -12,12 +12,10 @@ export { clearTopic } from './clearTopic'
|
||||
|
||||
export { moveSelectionUpOrDownwards, moveInward, moveOutward } from './visibleTreeTraversal'
|
||||
|
||||
export const selectTopic = (topic: q.TreeNode<TopicViewModel>) => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
debouncedSelectTopic(topic, dispatch, getState)
|
||||
}
|
||||
export const selectTopic =
|
||||
(topic: q.TreeNode<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
debouncedSelectTopic(topic, dispatch, getState)
|
||||
}
|
||||
|
||||
const debouncedSelectTopic = debounce(
|
||||
(topic: q.TreeNode<TopicViewModel>, dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
@@ -74,25 +72,26 @@ function destroyUnreferencedTree(state: AppState) {
|
||||
}
|
||||
}
|
||||
|
||||
export const resetStore = () => (dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
|
||||
destroyUnreferencedTree(getState())
|
||||
export const resetStore =
|
||||
() =>
|
||||
(dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
|
||||
destroyUnreferencedTree(getState())
|
||||
|
||||
return dispatch({
|
||||
type: ActionTypes.TREE_RESET_STORE,
|
||||
})
|
||||
}
|
||||
return dispatch({
|
||||
type: ActionTypes.TREE_RESET_STORE,
|
||||
})
|
||||
}
|
||||
|
||||
export const showTree = (tree: q.Tree<TopicViewModel> | undefined) => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
): AnyAction => {
|
||||
destroyUnreferencedTree(getState())
|
||||
export const showTree =
|
||||
(tree: q.Tree<TopicViewModel> | undefined) =>
|
||||
(dispatch: Dispatch<any>, getState: () => AppState): AnyAction => {
|
||||
destroyUnreferencedTree(getState())
|
||||
|
||||
return dispatch({
|
||||
tree,
|
||||
type: ActionTypes.TREE_SHOW_TREE,
|
||||
})
|
||||
}
|
||||
return dispatch({
|
||||
tree,
|
||||
type: ActionTypes.TREE_SHOW_TREE,
|
||||
})
|
||||
}
|
||||
|
||||
export const togglePause = (tree?: q.Tree<TopicViewModel>) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const paused = getState().tree.get('paused')
|
||||
|
||||
@@ -5,52 +5,50 @@ import { makePublishEvent, rendererEvents } from '../../../events'
|
||||
import { moveSelectionUpOrDownwards } from './visibleTreeTraversal'
|
||||
import { globalActions } from '.'
|
||||
|
||||
export const clearTopic = (topic: q.TreeNode<any>, recursive: boolean) => async (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
const topicsForPurging = recursive ? [topic, ...topic.childTopics()] : [topic]
|
||||
export const clearTopic =
|
||||
(topic: q.TreeNode<any>, recursive: boolean) => async (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const topicsForPurging = recursive ? [topic, ...topic.childTopics()] : [topic]
|
||||
|
||||
if (recursive) {
|
||||
const topicCount = topic.childTopicCount()
|
||||
if (recursive) {
|
||||
const topicCount = topic.childTopicCount()
|
||||
|
||||
const topicDelta = topic.hasMessage() ? -1 : 0
|
||||
const childTopicsMessage =
|
||||
topicCount + topicDelta > 0
|
||||
? ` and ${topicCount + topicDelta} child ${topicCount + topicDelta === 1 ? 'topic' : 'topics'}`
|
||||
: ''
|
||||
const topicDelta = topic.hasMessage() ? -1 : 0
|
||||
const childTopicsMessage =
|
||||
topicCount + topicDelta > 0
|
||||
? ` and ${topicCount + topicDelta} child ${topicCount + topicDelta === 1 ? 'topic' : 'topics'}`
|
||||
: ''
|
||||
|
||||
const confirmed = await dispatch(
|
||||
globalActions.requestConfirmation(
|
||||
'Confirm delete',
|
||||
`Do you want to clear "${topic.path()}"${childTopicsMessage}?\n\nThis function will send an empty payload (QoS 0, retain) to this and every subtopic, clearing retained topics in the process. Only use this function if you know what you are doing.`
|
||||
const confirmed = await dispatch(
|
||||
globalActions.requestConfirmation(
|
||||
'Confirm delete',
|
||||
`Do you want to clear "${topic.path()}"${childTopicsMessage}?\n\nThis function will send an empty payload (QoS 0, retain) to this and every subtopic, clearing retained topics in the process. Only use this function if you know what you are doing.`
|
||||
)
|
||||
)
|
||||
)
|
||||
if (!confirmed) {
|
||||
if (!confirmed) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(moveSelectionUpOrDownwards('next'))
|
||||
|
||||
const { connectionId } = getState().connection
|
||||
if (!connectionId) {
|
||||
return
|
||||
}
|
||||
const publishEvent = makePublishEvent(connectionId)
|
||||
|
||||
topicsForPurging
|
||||
.filter(t => t.path() !== '' && t.hasMessage())
|
||||
.map(t => t.path())
|
||||
.forEach((path, idx) => {
|
||||
const mqttMessage = {
|
||||
topic: path,
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
messageId: undefined,
|
||||
}
|
||||
// Rate limit deletion
|
||||
setTimeout(() => rendererEvents.emit(publishEvent, mqttMessage), 20 * idx)
|
||||
})
|
||||
}
|
||||
|
||||
dispatch(moveSelectionUpOrDownwards('next'))
|
||||
|
||||
const { connectionId } = getState().connection
|
||||
if (!connectionId) {
|
||||
return
|
||||
}
|
||||
const publishEvent = makePublishEvent(connectionId)
|
||||
|
||||
topicsForPurging
|
||||
.filter(t => t.path() !== '' && t.hasMessage())
|
||||
.map(t => t.path())
|
||||
.forEach((path, idx) => {
|
||||
const mqttMessage = {
|
||||
topic: path,
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
messageId: undefined,
|
||||
}
|
||||
// Rate limit deletion
|
||||
setTimeout(() => rendererEvents.emit(publishEvent, mqttMessage), 20 * idx)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,53 +6,56 @@ import { SettingsState } from '../reducers/Settings'
|
||||
import { sortedNodes } from '../sortedNodes'
|
||||
import { TopicViewModel } from '../model/TopicViewModel'
|
||||
|
||||
export const moveSelectionUpOrDownwards = (direction: 'next' | 'previous') => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
const tree = state.tree.get('tree')
|
||||
export const moveSelectionUpOrDownwards =
|
||||
(direction: 'next' | 'previous') =>
|
||||
(dispatch: Dispatch<any>, getState: () => AppState): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
const tree = state.tree.get('tree')
|
||||
|
||||
if (!selected || !tree) {
|
||||
if (tree) {
|
||||
dispatch(selectTopic(tree))
|
||||
if (!selected || !tree) {
|
||||
if (tree) {
|
||||
dispatch(selectTopic(tree))
|
||||
}
|
||||
return
|
||||
}
|
||||
const nextTreeNode = nextVisibleElementInTree(state.settings, tree, selected, direction)
|
||||
if (nextTreeNode && nextTreeNode.viewModel) {
|
||||
dispatch(selectTopic(nextTreeNode))
|
||||
}
|
||||
return
|
||||
}
|
||||
const nextTreeNode = nextVisibleElementInTree(state.settings, tree, selected, direction)
|
||||
if (nextTreeNode && nextTreeNode.viewModel) {
|
||||
dispatch(selectTopic(nextTreeNode))
|
||||
}
|
||||
}
|
||||
|
||||
export const moveInward = () => (dispatch: Dispatch<any>, getState: () => AppState): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
if (!selected || !selected.viewModel) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!selected.viewModel.isExpanded() && selected.edgeCount() > 0) {
|
||||
selected.viewModel.setExpanded(true, true)
|
||||
} else {
|
||||
dispatch(moveSelectionUpOrDownwards('next'))
|
||||
}
|
||||
}
|
||||
export const moveInward =
|
||||
() =>
|
||||
(dispatch: Dispatch<any>, getState: () => AppState): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
if (!selected || !selected.viewModel) {
|
||||
return
|
||||
}
|
||||
|
||||
export const moveOutward = () => (dispatch: Dispatch<any>, getState: () => AppState): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
if (!selected || !selected.viewModel) {
|
||||
return
|
||||
if (!selected.viewModel.isExpanded() && selected.edgeCount() > 0) {
|
||||
selected.viewModel.setExpanded(true, true)
|
||||
} else {
|
||||
dispatch(moveSelectionUpOrDownwards('next'))
|
||||
}
|
||||
}
|
||||
|
||||
if (selected.viewModel.isExpanded() && selected.edgeCount() > 0) {
|
||||
selected.viewModel.setExpanded(false, true)
|
||||
} else {
|
||||
dispatch(moveSelectionUpOrDownwards('previous'))
|
||||
export const moveOutward =
|
||||
() =>
|
||||
(dispatch: Dispatch<any>, getState: () => AppState): any => {
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
if (!selected || !selected.viewModel) {
|
||||
return
|
||||
}
|
||||
|
||||
if (selected.viewModel.isExpanded() && selected.edgeCount() > 0) {
|
||||
selected.viewModel.setExpanded(false, true)
|
||||
} else {
|
||||
dispatch(moveSelectionUpOrDownwards('previous'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isTreeNodeVisible(treeNode: q.TreeNode<any>) {
|
||||
return Boolean(treeNode.viewModel)
|
||||
|
||||
@@ -12,6 +12,7 @@ import { ConfirmationRequest } from '../reducers/Global'
|
||||
import { connect } from 'react-redux'
|
||||
import { globalActions, settingsActions } from '../actions'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
;(window as any).global = window
|
||||
|
||||
const Settings = React.lazy(() => import('./SettingsDrawer/Settings'))
|
||||
const ContentView = React.lazy(() => import('./Layout/ContentView'))
|
||||
@@ -66,6 +67,8 @@ class App extends React.PureComponent<Props, {}> {
|
||||
return null
|
||||
}
|
||||
|
||||
const anyProps: any = {}
|
||||
|
||||
return (
|
||||
<div className={centerContent}>
|
||||
<CssBaseline />
|
||||
@@ -73,7 +76,7 @@ class App extends React.PureComponent<Props, {}> {
|
||||
<ConfirmationDialog confirmationRequests={this.props.confirmationRequests} />
|
||||
{this.renderNotification()}
|
||||
<React.Suspense fallback={<div></div>}>
|
||||
<Settings />
|
||||
<Settings {...anyProps} />
|
||||
</React.Suspense>
|
||||
<div className={centerContent}>
|
||||
<div className={`${settingsVisible ? contentShift : content}`}>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import * as React from 'react'
|
||||
import Add from '@material-ui/icons/Add'
|
||||
import ClearAdornment from '../helper/ClearAdornment'
|
||||
import Delete from '@material-ui/icons/Delete'
|
||||
import Lock from '@material-ui/icons/Lock'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { Button, Theme, Tooltip, Typography } from '@material-ui/core'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import { Theme, withStyles } from '@material-ui/core'
|
||||
import cursor from './cursor.png'
|
||||
const cursor = require('./cursor.png')
|
||||
|
||||
interface State {
|
||||
enabled: boolean
|
||||
|
||||
@@ -5,7 +5,7 @@ let heapdump: any
|
||||
|
||||
function writeHeapdump(path?: string) {
|
||||
if (!heapdump) {
|
||||
heapdump = require('heapdump')
|
||||
//<heapdump = require('heapdump')
|
||||
}
|
||||
|
||||
heapdump.writeSnapshot(path || `${Date.now()}.heapsnapshot`)
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as React from 'react'
|
||||
import PersistentStorage from '../utils/PersistentStorage'
|
||||
import SentimentDissatisfied from '@material-ui/icons/SentimentDissatisfied'
|
||||
import Warning from '@material-ui/icons/Warning'
|
||||
import { electronRendererTelemetry } from 'electron-telemetry'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { Button, Modal, Paper, Toolbar, Typography } from '@material-ui/core'
|
||||
|
||||
@@ -33,7 +32,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
public componentDidCatch(error: Error, errorInfo: any) {
|
||||
electronRendererTelemetry.trackError(error)
|
||||
// electronRendererTelemetry.trackError(error)
|
||||
console.log('did catch', error)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,17 @@ import DateFormatter from '../helper/DateFormatter'
|
||||
import { AppState } from '../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
import { connect } from 'react-redux'
|
||||
import { Input, InputLabel, MenuItem, Select, StyleRulesCallback, Theme } from '@material-ui/core'
|
||||
import { Input, InputLabel, MenuItem, Select, Theme } from '@material-ui/core'
|
||||
import { settingsActions } from '../../actions'
|
||||
import { withStyles } from '@material-ui/styles'
|
||||
const moment = require('moment/min/moment-with-locales')
|
||||
|
||||
function importAll(r: any) {
|
||||
r.keys().forEach(r)
|
||||
}
|
||||
// @ts-expect-error -- webpack require
|
||||
importAll(require.context('moment/locale', true, /\.js$/))
|
||||
|
||||
const moment = require('moment')
|
||||
|
||||
interface Props {
|
||||
actions: {
|
||||
|
||||
@@ -43,9 +43,9 @@ class CodeDiff extends React.PureComponent<Props, State> {
|
||||
private plottableLiteralsIndexedWithLineNumbers() {
|
||||
const allLiterals = this.isValidJson(this.props.current) ? literalsMappedByLines(this.props.current) || [] : []
|
||||
|
||||
return allLiterals.map((l: JsonPropertyLocation) => (isPlottable(l.value) ? l : undefined)) as Array<
|
||||
JsonPropertyLocation
|
||||
>
|
||||
return allLiterals.map((l: JsonPropertyLocation) =>
|
||||
isPlottable(l.value) ? l : undefined
|
||||
) as Array<JsonPropertyLocation>
|
||||
}
|
||||
|
||||
private renderStyledCodeLines(changes: Array<Diff.Change>) {
|
||||
|
||||
@@ -30,4 +30,5 @@ const Panel = (props: {
|
||||
)
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
export default withStyles(styles)(Panel)
|
||||
|
||||
@@ -122,7 +122,7 @@ const EditorMode = memo(function EditorMode(props: {
|
||||
const str = JSON.stringify(JSON.parse(props.payload), undefined, ' ')
|
||||
updatePayload(str)
|
||||
} catch (error) {
|
||||
props.globalActions.showError(`Format error: ${error.message}`)
|
||||
props.globalActions.showError(`Format error: ${(error as Error)?.message}`)
|
||||
}
|
||||
}
|
||||
}, [props.payload])
|
||||
|
||||
@@ -40,7 +40,7 @@ function ActionButtons(props: {
|
||||
</Tooltip>
|
||||
</ToggleButton>
|
||||
<ToggleButton className={props.classes.toggleButton} value="raw" id="valueRendererDisplayMode-raw">
|
||||
<Tooltip title="Raw / formatted JSON">
|
||||
<Tooltip title="Raw / formatted JSON / formatted sparkplugb protojson">
|
||||
<span>
|
||||
<Reorder className={props.classes.toggleButtonIcon} />
|
||||
</span>
|
||||
|
||||
@@ -128,4 +128,5 @@ const styles = (theme: Theme) => ({
|
||||
},
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(ValuePanel))
|
||||
|
||||
@@ -4,9 +4,9 @@ import CodeDiff from '../CodeDiff'
|
||||
import { AppState } from '../../../reducers'
|
||||
import { Base64Message } from '../../../../../backend/src/Model/Base64Message'
|
||||
import { connect } from 'react-redux'
|
||||
import { default as ReactResizeDetector } from 'react-resize-detector'
|
||||
import { ValueRendererDisplayMode } from '../../../reducers/Settings'
|
||||
import { Typography, Fade, Grow } from '@material-ui/core'
|
||||
import { Fade } from '@material-ui/core'
|
||||
import { Decoder } from '../../../../../backend/src/Model/Decoder'
|
||||
|
||||
interface Props {
|
||||
message: q.Message
|
||||
@@ -83,7 +83,12 @@ class ValueRenderer extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
public render() {
|
||||
return <div style={{ padding: '0px 0px 8px 0px', width: '100%' }}>{this.renderValue()}</div>
|
||||
return (
|
||||
<div style={{ padding: '0px 0px 8px 0px', width: '100%' }}>
|
||||
{this.props.message?.payload?.decoder === Decoder.SPARKPLUG && 'Decoded SparkplugB'}
|
||||
{this.renderValue()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
public renderValue() {
|
||||
|
||||
@@ -37,7 +37,7 @@ function nodeToHistory(startTime: number | undefined, history: q.MessageHistory)
|
||||
function nodeDotPathToHistory(startTime: number | undefined, history: q.MessageHistory, dotPath: string) {
|
||||
return filterUsingTimeRange(startTime, history.toArray())
|
||||
.map((message: q.Message) => {
|
||||
let json = {}
|
||||
let json: any = {}
|
||||
try {
|
||||
json = message.payload ? JSON.parse(Base64Message.toUnicodeString(message.payload)) : {}
|
||||
} catch (ignore) {}
|
||||
|
||||
@@ -91,23 +91,26 @@ class TreeComponent extends React.PureComponent<Props, State> {
|
||||
const updateInterval = Math.max(expectedRenderTime * 7, 300)
|
||||
const timeUntilNextUpdate = updateInterval - (performance.now() - this.renderTime)
|
||||
|
||||
this.updateTimer = setTimeout(() => {
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
this.updateTimer && clearTimeout(this.updateTimer)
|
||||
this.updateTimer = undefined
|
||||
this.renderTime = performance.now()
|
||||
this.updateTimer = setTimeout(
|
||||
() => {
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
this.updateTimer && clearTimeout(this.updateTimer)
|
||||
this.updateTimer = undefined
|
||||
this.renderTime = performance.now()
|
||||
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
this.setState({ lastUpdate: this.renderTime })
|
||||
},
|
||||
{ timeout: 100 }
|
||||
)
|
||||
},
|
||||
{ timeout: 500 }
|
||||
)
|
||||
}, Math.max(0, timeUntilNextUpdate))
|
||||
window.requestIdleCallback(
|
||||
() => {
|
||||
this.setState({ lastUpdate: this.renderTime })
|
||||
},
|
||||
{ timeout: 100 }
|
||||
)
|
||||
},
|
||||
{ timeout: 500 }
|
||||
)
|
||||
},
|
||||
Math.max(0, timeUntilNextUpdate)
|
||||
)
|
||||
}
|
||||
|
||||
public componentWillUpdate() {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { updateNotifierActions } from '../actions'
|
||||
|
||||
import { Button, IconButton, Modal, Paper, Snackbar, SnackbarContent, Typography } from '@material-ui/core'
|
||||
import { rendererRpc, getAppVersion } from '../../../events'
|
||||
|
||||
interface Props {
|
||||
showUpdateNotification: boolean
|
||||
@@ -50,18 +51,21 @@ class UpdateNotifier extends React.PureComponent<Props, State> {
|
||||
super(props)
|
||||
this.state = { newerVersions: [] }
|
||||
|
||||
const ownVersion = electron.remote.app.getVersion()
|
||||
this.fetchReleases().then(releases => {
|
||||
const newerVersions = releases
|
||||
.filter(release => this.allowPrereleaseIfOwnVersionIsBeta(release, ownVersion))
|
||||
.filter(release => compareVersions(release.tag_name, ownVersion) > 0)
|
||||
.sort((a, b) => compareVersions(b.tag_name, a.tag_name))
|
||||
this.checkForUpdates()
|
||||
}
|
||||
|
||||
if (newerVersions.length > 0) {
|
||||
this.setState({ newerVersions })
|
||||
this.props.actions.showUpdateNotification(true)
|
||||
}
|
||||
})
|
||||
private async checkForUpdates() {
|
||||
const ownVersion = await rendererRpc.call(getAppVersion, undefined, 10000)
|
||||
const releases = await this.fetchReleases()
|
||||
const newerVersions = releases
|
||||
.filter(release => this.allowPrereleaseIfOwnVersionIsBeta(release, ownVersion))
|
||||
.filter(release => compareVersions(release.tag_name, ownVersion) > 0)
|
||||
.sort((a, b) => compareVersions(b.tag_name, a.tag_name))
|
||||
|
||||
if (newerVersions.length > 0) {
|
||||
this.setState({ newerVersions })
|
||||
this.props.actions.showUpdateNotification(true)
|
||||
}
|
||||
}
|
||||
|
||||
private allowPrereleaseIfOwnVersionIsBeta(release: GithubRelease, ownVersion: string) {
|
||||
|
||||
@@ -45,9 +45,11 @@ const initialStateFactory = Record<TreeStateModel>({
|
||||
filter: undefined,
|
||||
})
|
||||
|
||||
const setPaused = (pause: boolean) => (state: TreeState, action: ShowTree): TreeState => {
|
||||
return state.set('paused', pause)
|
||||
}
|
||||
const setPaused =
|
||||
(pause: boolean) =>
|
||||
(state: TreeState, action: ShowTree): TreeState => {
|
||||
return state.set('paused', pause)
|
||||
}
|
||||
|
||||
const actions: {
|
||||
[s: string]: (state: TreeState, action: ReduxAction) => TreeState
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import { rendererEvents } from '../../../events'
|
||||
import { v4 } from 'uuid'
|
||||
import { rendererRpc } from '../../../events'
|
||||
|
||||
import {
|
||||
storageStoreEvent,
|
||||
makeStorageResponseEvent,
|
||||
storageLoadEvent,
|
||||
storageClearEvent,
|
||||
makeStorageAcknowledgementEvent,
|
||||
} from '../../../events/StorageEvents'
|
||||
import { storageStoreEvent, storageLoadEvent, storageClearEvent } from '../../../events/StorageEvents'
|
||||
|
||||
export interface StorageIdentifier<Model> {
|
||||
id: string
|
||||
@@ -20,71 +13,27 @@ export interface PersistentStorage {
|
||||
}
|
||||
|
||||
class RemoteStorage implements PersistentStorage {
|
||||
private timeoutCallback(event: any, callback: any, reject: any) {
|
||||
setTimeout(() => {
|
||||
reject('remote storage timeout')
|
||||
rendererEvents.unsubscribe(event, callback)
|
||||
}, 10000)
|
||||
}
|
||||
|
||||
private expectAck(transactionId: string): Promise<void> {
|
||||
const ack = makeStorageAcknowledgementEvent(transactionId)
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
const callback = (msg: any) => {
|
||||
if (msg && msg.error) {
|
||||
reject(msg.error)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
rendererEvents.unsubscribe(ack, callback)
|
||||
}
|
||||
rendererEvents.subscribe(ack, callback)
|
||||
this.timeoutCallback(ack, callback, reject)
|
||||
})
|
||||
}
|
||||
|
||||
public store<Model>(identifier: StorageIdentifier<Model>, data: Model): Promise<void> {
|
||||
const transactionId = v4()
|
||||
const expectation = this.expectAck(transactionId)
|
||||
rendererEvents.emit(storageStoreEvent, {
|
||||
return rendererRpc.call(storageStoreEvent, {
|
||||
data,
|
||||
transactionId,
|
||||
store: identifier.id,
|
||||
})
|
||||
return expectation
|
||||
}
|
||||
|
||||
public load<Model>(identifier: StorageIdentifier<Model>): Promise<Model | undefined> {
|
||||
const transactionId = v4()
|
||||
const responseEvent = makeStorageResponseEvent(transactionId)
|
||||
public async load<Model>(identifier: StorageIdentifier<Model>): Promise<Model | undefined> {
|
||||
const result = await rendererRpc.call(
|
||||
storageLoadEvent,
|
||||
{
|
||||
store: identifier.id,
|
||||
},
|
||||
10000
|
||||
)
|
||||
|
||||
const promise = new Promise<Model>((resolve, reject) => {
|
||||
const callback = (msg: any) => {
|
||||
if (msg.error) {
|
||||
reject(msg.error)
|
||||
} else {
|
||||
resolve(msg.data)
|
||||
}
|
||||
rendererEvents.unsubscribe(responseEvent, callback)
|
||||
}
|
||||
rendererEvents.subscribe(responseEvent, callback)
|
||||
this.timeoutCallback(responseEvent, callback, reject)
|
||||
})
|
||||
|
||||
rendererEvents.emit(storageLoadEvent, {
|
||||
transactionId,
|
||||
store: identifier.id,
|
||||
})
|
||||
|
||||
return promise
|
||||
return (result as any).data
|
||||
}
|
||||
|
||||
public clear(): Promise<void> {
|
||||
const transactionId = v4()
|
||||
const expectation = this.expectAck(transactionId)
|
||||
|
||||
rendererEvents.emit(storageClearEvent, { transactionId })
|
||||
return expectation
|
||||
return rendererRpc.call(storageClearEvent, undefined, 10000)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { electronRendererTelemetry } from 'electron-telemetry'
|
||||
// import { electronRendererTelemetry } from 'electron-telemetry'
|
||||
|
||||
const telemetry = electronRendererTelemetry
|
||||
electronRendererTelemetry.registerErrorHandler()
|
||||
// const telemetry = electronRendererTelemetry
|
||||
// electronRendererTelemetry.registerErrorHandler()
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
export const selectTextWithCtrlA = (options?: { targetSelector: string }) => (
|
||||
e: React.KeyboardEvent<HTMLDivElement>
|
||||
) => {
|
||||
const isCtrlA = (e.metaKey || e.ctrlKey) && e.key === 'a'
|
||||
export const selectTextWithCtrlA =
|
||||
(options?: { targetSelector: string }) => (e: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
const isCtrlA = (e.metaKey || e.ctrlKey) && e.key === 'a'
|
||||
|
||||
if (isCtrlA && window.getSelection) {
|
||||
e.persist()
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const selection = window.getSelection()
|
||||
const range = document.createRange()
|
||||
const eventTarget = e.target as HTMLElement
|
||||
const target: HTMLElement | null = options ? eventTarget.querySelector(options.targetSelector) : eventTarget
|
||||
if (isCtrlA && window.getSelection) {
|
||||
e.persist()
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
const selection = window.getSelection()
|
||||
const range = document.createRange()
|
||||
const eventTarget = e.target as HTMLElement
|
||||
const target: HTMLElement | null = options ? eventTarget.querySelector(options.targetSelector) : eventTarget
|
||||
|
||||
if (!target) {
|
||||
console.error('Could not find matching target for Ctrl+A Event')
|
||||
}
|
||||
if (selection && target) {
|
||||
range.selectNodeContents(target)
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
if (!target) {
|
||||
console.error('Could not find matching target for Ctrl+A Event')
|
||||
}
|
||||
if (selection && target) {
|
||||
range.selectNodeContents(target)
|
||||
selection.removeAllRanges()
|
||||
selection.addRange(range)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-23
@@ -1,27 +1,27 @@
|
||||
import { electronRendererTelemetry } from 'electron-telemetry'
|
||||
// import { electronRendererTelemetry } from 'electron-telemetry'
|
||||
|
||||
// Used to determine long-time-stability and memory leaks
|
||||
function trackProcessStatistics() {
|
||||
setInterval(() => {
|
||||
try {
|
||||
electronRendererTelemetry.trackCustomEvent({
|
||||
name: 'heapStatistics',
|
||||
payload: process.getHeapStatistics(),
|
||||
})
|
||||
electronRendererTelemetry.trackCustomEvent({
|
||||
name: 'cpuUsage',
|
||||
payload: process.getCPUUsage(),
|
||||
})
|
||||
electronRendererTelemetry.trackCustomEvent({
|
||||
name: 'runningSince',
|
||||
payload: performance.now(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}, 60 * 1000)
|
||||
}
|
||||
trackProcessStatistics()
|
||||
// function trackProcessStatistics() {
|
||||
// setInterval(() => {
|
||||
// try {
|
||||
// electronRendererTelemetry.trackCustomEvent({
|
||||
// name: 'heapStatistics',
|
||||
// payload: process.getHeapStatistics(),
|
||||
// })
|
||||
// electronRendererTelemetry.trackCustomEvent({
|
||||
// name: 'cpuUsage',
|
||||
// payload: process.getCPUUsage(),
|
||||
// })
|
||||
// electronRendererTelemetry.trackCustomEvent({
|
||||
// name: 'runningSince',
|
||||
// payload: performance.now(),
|
||||
// })
|
||||
// } catch (error) {
|
||||
// console.error(error)
|
||||
// }
|
||||
// }, 60 * 1000)
|
||||
// }
|
||||
// trackProcessStatistics()
|
||||
|
||||
// Log reducer event names to determine what functionality is used and how to reproduce reported errors
|
||||
export function trackEvent(name: string) {
|
||||
@@ -30,6 +30,6 @@ export function trackEvent(name: string) {
|
||||
}
|
||||
const blacklist = ['CONNECTION_SET_HEALTH']
|
||||
if (blacklist.indexOf(name) === -1) {
|
||||
electronRendererTelemetry.trackEvent(name)
|
||||
// electronRendererTelemetry.trackEvent(name)
|
||||
}
|
||||
}
|
||||
|
||||
+23
-6
@@ -4,21 +4,38 @@
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"strict": true,
|
||||
"lib": ["es2017", "dom"],
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./build/",
|
||||
"sourceMap": true,
|
||||
"module": "esnext",
|
||||
"target": "es2017",
|
||||
"jsx": "react",
|
||||
"types": ["react"],
|
||||
"allowSyntheticDefaultImports": true
|
||||
"paths": {
|
||||
"react": [
|
||||
"./node_modules/@types/react"
|
||||
]
|
||||
},
|
||||
"types": [
|
||||
"react"
|
||||
],
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
"exclude": ["**/*.d.ts", ".src/**/*.png"],
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.d.ts",
|
||||
".src/**/*.png",
|
||||
"./node_modules"
|
||||
],
|
||||
"awesomeTypescriptLoaderOptions": {
|
||||
"useCache": true,
|
||||
"transpileModule": true,
|
||||
"errorsAsWarnings": true
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
-25
@@ -1,7 +1,6 @@
|
||||
// const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
@@ -18,12 +17,11 @@ module.exports = {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
minSize: 30000,
|
||||
maxSize: 0,
|
||||
minChunks: 1,
|
||||
maxAsyncRequests: 5,
|
||||
maxInitialRequests: 3,
|
||||
automaticNameDelimiter: '~',
|
||||
name: true,
|
||||
// name: true,
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
test: /[\\/]node_modules[\\/](react|react-dom|@material-ui|popper\.js|react|react-redux|prop-types|jss|redux|scheduler|react-transition-group)[\\/]/,
|
||||
@@ -32,6 +30,7 @@ module.exports = {
|
||||
priority: -10,
|
||||
},
|
||||
default: {
|
||||
name: 'default',
|
||||
minChunks: 2,
|
||||
priority: -20,
|
||||
reuseExistingChunk: true,
|
||||
@@ -55,13 +54,7 @@ module.exports = {
|
||||
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: 'awesome-typescript-loader',
|
||||
options: {
|
||||
reportFiles: [
|
||||
"src/**/*.{ts,tsx}",
|
||||
"../backend/src/**/*.{ts,tsx}"
|
||||
]
|
||||
}
|
||||
loader: 'ts-loader',
|
||||
},
|
||||
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
|
||||
{ enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' },
|
||||
@@ -78,27 +71,26 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: {
|
||||
loader: 'node-loader',
|
||||
options: {
|
||||
modules: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
// {
|
||||
// test: /\.node$/,
|
||||
// use: {
|
||||
// loader: 'node-loader',
|
||||
// options: {
|
||||
// modules: true,
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
],
|
||||
},
|
||||
|
||||
// node: { global: true },
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({ template: './index.html', file: './build/index.html', inject: false }),
|
||||
// new BundleAnalyzerPlugin(),
|
||||
new HardSourceWebpackPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: /\.\/build\/Debug\/addon/,
|
||||
contextRegExp: /heapdump$/
|
||||
}),
|
||||
// new webpack.IgnorePlugin({
|
||||
// resourceRegExp: /\.\/build\/Debug\/addon/,
|
||||
// contextRegExp: /heapdump$/
|
||||
// }),
|
||||
],
|
||||
|
||||
// When importing a module whose path matches one of the following, just
|
||||
|
||||
+2674
-5041
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -7,13 +7,15 @@ cache:
|
||||
- '%LOCALAPPDATA%\electron-builder\cache'
|
||||
|
||||
install:
|
||||
- ps: Install-Product node 10
|
||||
- ps: Install-Product node 19
|
||||
|
||||
build_script:
|
||||
- yarn
|
||||
- yarn build
|
||||
- yarn prepare-release
|
||||
- yarn package appx
|
||||
- yarn prepare-release
|
||||
- yarn package linux
|
||||
|
||||
test_script:
|
||||
- yarn lint
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
"debug": "ts-node --inspect ./src/index.ts",
|
||||
"postinstall": "yarn build"
|
||||
},
|
||||
"engines": {
|
||||
"node": "19"
|
||||
},
|
||||
"author": "",
|
||||
"license": "CC-BY-ND-4.0",
|
||||
"nyc": {
|
||||
@@ -39,6 +42,8 @@
|
||||
"fs-extra": "^8.0.1",
|
||||
"js-base64": "^2.5.1",
|
||||
"lowdb": "^1.0.0",
|
||||
"mqtt": "^3.0.0"
|
||||
"mqtt": "^3.0.0",
|
||||
"protobufjs": "~6.11.2",
|
||||
"long": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,8 @@ import * as FileAsync from 'lowdb/adapters/FileAsync'
|
||||
import * as fs from 'fs-extra'
|
||||
import * as lowdb from 'lowdb'
|
||||
import * as path from 'path'
|
||||
import { backendEvents } from '../../events'
|
||||
import {
|
||||
makeStorageAcknowledgementEvent,
|
||||
makeStorageResponseEvent,
|
||||
storageClearEvent,
|
||||
storageLoadEvent,
|
||||
storageStoreEvent,
|
||||
} from '../../events/StorageEvents'
|
||||
import { backendRpc } from '../../events'
|
||||
import { storageClearEvent, storageLoadEvent, storageStoreEvent } from '../../events/StorageEvents'
|
||||
|
||||
export default class ConfigStorage {
|
||||
private file: string
|
||||
@@ -32,56 +26,26 @@ export default class ConfigStorage {
|
||||
}
|
||||
|
||||
public async init() {
|
||||
backendEvents.subscribe(storageStoreEvent, async event => {
|
||||
const ack = makeStorageAcknowledgementEvent(event.transactionId)
|
||||
try {
|
||||
const db = await this.getDb()
|
||||
await db.set(event.store, event.data).write()
|
||||
backendEvents.emit(ack, undefined)
|
||||
} catch (error) {
|
||||
backendEvents.emit(ack, {
|
||||
error,
|
||||
transactionId: event.transactionId,
|
||||
store: event.store,
|
||||
})
|
||||
throw error
|
||||
backendRpc.on(storageStoreEvent, async event => {
|
||||
const db = await this.getDb()
|
||||
await db.set(event.store, event.data).write()
|
||||
return
|
||||
})
|
||||
|
||||
backendRpc.on(storageLoadEvent, async event => {
|
||||
const db = await this.getDb()
|
||||
const data = await db.get(event.store).value()
|
||||
return {
|
||||
data,
|
||||
store: event.store,
|
||||
}
|
||||
})
|
||||
|
||||
backendEvents.subscribe(storageLoadEvent, async event => {
|
||||
const responseEvent = makeStorageResponseEvent(event.transactionId)
|
||||
try {
|
||||
const db = await this.getDb()
|
||||
const data = await db.get(event.store).value()
|
||||
backendEvents.emit(responseEvent, {
|
||||
data,
|
||||
transactionId: event.transactionId,
|
||||
store: event.store,
|
||||
})
|
||||
} catch (error) {
|
||||
backendEvents.emit(responseEvent, {
|
||||
error,
|
||||
transactionId: event.transactionId,
|
||||
store: event.store,
|
||||
})
|
||||
throw error
|
||||
}
|
||||
})
|
||||
|
||||
backendEvents.subscribe(storageClearEvent, async event => {
|
||||
try {
|
||||
const db = await this.getDb()
|
||||
const keys = await db.keys().value()
|
||||
for (const key of keys) {
|
||||
await db.unset(key).write()
|
||||
}
|
||||
backendEvents.emit(makeStorageAcknowledgementEvent(event.transactionId), undefined)
|
||||
} catch (error) {
|
||||
backendEvents.emit(makeStorageAcknowledgementEvent(event.transactionId), {
|
||||
error,
|
||||
transactionId: event.transactionId,
|
||||
})
|
||||
throw error
|
||||
backendRpc.on(storageClearEvent, async event => {
|
||||
const db = await this.getDb()
|
||||
const keys = await db.keys().value()
|
||||
for (const key of keys) {
|
||||
await db.unset(key).write()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as Url from 'url'
|
||||
import { URL } from 'url'
|
||||
|
||||
import { Client, connect as mqttConnect } from 'mqtt'
|
||||
import { DataSource, DataSourceStateMachine } from './'
|
||||
@@ -41,13 +41,13 @@ export class MqttSource implements DataSource<MqttOptions> {
|
||||
const urlStr = options.tls ? options.url.replace(/^(mqtt|ws):/, '$1s:') : options.url
|
||||
let url
|
||||
try {
|
||||
url = Url.parse(urlStr)
|
||||
url = new URL(urlStr)
|
||||
} catch (error) {
|
||||
this.stateMachine.setError(error)
|
||||
this.stateMachine.setError(error as Error)
|
||||
throw error
|
||||
}
|
||||
|
||||
const client = mqttConnect(url, {
|
||||
const client = mqttConnect(url.toString(), {
|
||||
resubscribe: false,
|
||||
rejectUnauthorized: options.certValidation,
|
||||
username: options.username,
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
const { Base64 } = require('js-base64')
|
||||
import { Base64 } from 'js-base64'
|
||||
import { Decoder } from './Decoder'
|
||||
|
||||
export class Base64Message {
|
||||
private base64Message: string
|
||||
private unicodeValue: string
|
||||
|
||||
public decoder: Decoder
|
||||
public length: number
|
||||
|
||||
private constructor(base64Str: string) {
|
||||
this.base64Message = base64Str
|
||||
this.unicodeValue = Base64.decode(base64Str)
|
||||
this.length = base64Str.length
|
||||
this.decoder = Decoder.NONE
|
||||
}
|
||||
|
||||
public static toUnicodeString(message: Base64Message) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum Decoder {
|
||||
NONE,
|
||||
SPARKPLUG,
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ChangeBuffer } from './ChangeBuffer'
|
||||
import { Destroyable } from './Destroyable'
|
||||
import { EventBusInterface, EventDispatcher, makeConnectionMessageEvent, MqttMessage } from '../../../events'
|
||||
import { EventDispatcher, makeConnectionMessageEvent, MqttMessage, EventBusInterface } from '../../../events'
|
||||
import { TreeNode } from './'
|
||||
import { TreeNodeFactory } from './TreeNodeFactory'
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { readFileSync } from 'fs'
|
||||
import * as protobuf from 'protobufjs'
|
||||
import { Base64Message } from './Base64Message'
|
||||
import { Decoder } from './Decoder'
|
||||
|
||||
const buffer = readFileSync(require.resolve('../../../../res/sparkplug_b.proto'))
|
||||
const root = protobuf.parse(buffer.toString()).root
|
||||
export let SparkplugPayload = root.lookupType('com.cirruslink.sparkplug.protobuf.Payload')
|
||||
|
||||
export const SparkplugDecoder = {
|
||||
decode(input: Buffer): Base64Message | undefined {
|
||||
try {
|
||||
const message = Base64Message.fromString(
|
||||
JSON.stringify(SparkplugPayload.toObject(SparkplugPayload.decode(new Uint8Array(input))))
|
||||
)
|
||||
message.decoder = Decoder.SPARKPLUG
|
||||
return message
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
makePublishEvent,
|
||||
removeConnection,
|
||||
} from '../../events'
|
||||
import { SparkplugDecoder } from './Model/sparkplugb'
|
||||
|
||||
export class ConnectionManager {
|
||||
private connections: { [s: string]: DataSource<any> } = {}
|
||||
@@ -48,7 +49,7 @@ export class ConnectionManager {
|
||||
|
||||
backendEvents.emit(messageEvent, {
|
||||
topic,
|
||||
payload: Base64Message.fromBuffer(buffer),
|
||||
payload: SparkplugDecoder.decode(buffer) ?? Base64Message.fromBuffer(buffer),
|
||||
qos: packet.qos,
|
||||
retain: packet.retain,
|
||||
messageId: packet.messageId,
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
{
|
||||
"compileOnSave": true,
|
||||
"compilerOptions": {
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"outDir": "./build",
|
||||
"strict": true,
|
||||
"lib": ["es2017", "dom"],
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true
|
||||
},
|
||||
"includes": [
|
||||
@@ -18,4 +22,4 @@
|
||||
"**/*.d.ts",
|
||||
"typings"
|
||||
]
|
||||
}
|
||||
}
|
||||
+68
-516
@@ -2,537 +2,89 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
async-limiter@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
|
||||
integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
|
||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
|
||||
integrity sha1-m4sMxmPWaafY9vXQiToU00jzD78=
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
"@protobufjs/base64@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735"
|
||||
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
|
||||
|
||||
base64-js@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3"
|
||||
integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==
|
||||
"@protobufjs/codegen@^2.0.4":
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb"
|
||||
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
|
||||
|
||||
bl@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
|
||||
integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
|
||||
dependencies:
|
||||
readable-stream "^2.3.5"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
|
||||
callback-stream@^1.0.2:
|
||||
"@protobufjs/eventemitter@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callback-stream/-/callback-stream-1.1.0.tgz#4701a51266f06e06eaa71fc17233822d875f4908"
|
||||
integrity sha1-RwGlEmbwbgbqpx/BcjOCLYdfSQg=
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
readable-stream "> 1.0.0 < 3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70"
|
||||
integrity sha1-NVy8mLr61ZePntCV85diHx0Ga3A=
|
||||
|
||||
commist@^1.0.0:
|
||||
"@protobufjs/fetch@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/commist/-/commist-1.1.0.tgz#17811ec6978f6c15ee4de80c45c9beb77cee35d5"
|
||||
integrity sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45"
|
||||
integrity sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=
|
||||
dependencies:
|
||||
leven "^2.1.0"
|
||||
minimist "^1.1.0"
|
||||
"@protobufjs/aspromise" "^1.1.1"
|
||||
"@protobufjs/inquire" "^1.1.0"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
concat-stream@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^2.2.2"
|
||||
typedarray "^0.0.6"
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
"@protobufjs/float@^1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1"
|
||||
integrity sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=
|
||||
|
||||
d@1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
|
||||
integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
|
||||
dependencies:
|
||||
es5-ext "^0.10.50"
|
||||
type "^1.0.1"
|
||||
|
||||
duplexify@^3.5.1, duplexify@^3.6.0:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||
integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
|
||||
dependencies:
|
||||
end-of-stream "^1.0.0"
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.0.0"
|
||||
stream-shift "^1.0.0"
|
||||
|
||||
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.14:
|
||||
version "0.10.50"
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.50.tgz#6d0e23a0abdb27018e5ac4fd09b412bc5517a778"
|
||||
integrity sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==
|
||||
dependencies:
|
||||
es6-iterator "~2.0.3"
|
||||
es6-symbol "~3.1.1"
|
||||
next-tick "^1.0.0"
|
||||
|
||||
es6-iterator@~2.0.1, es6-iterator@~2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
|
||||
integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c=
|
||||
dependencies:
|
||||
d "1"
|
||||
es5-ext "^0.10.35"
|
||||
es6-symbol "^3.1.1"
|
||||
|
||||
es6-map@^0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0"
|
||||
integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=
|
||||
dependencies:
|
||||
d "1"
|
||||
es5-ext "~0.10.14"
|
||||
es6-iterator "~2.0.1"
|
||||
es6-set "~0.1.5"
|
||||
es6-symbol "~3.1.1"
|
||||
event-emitter "~0.3.5"
|
||||
|
||||
es6-set@~0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1"
|
||||
integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=
|
||||
dependencies:
|
||||
d "1"
|
||||
es5-ext "~0.10.14"
|
||||
es6-iterator "~2.0.1"
|
||||
es6-symbol "3.1.1"
|
||||
event-emitter "~0.3.5"
|
||||
|
||||
es6-symbol@3.1.1, es6-symbol@^3.1.1, es6-symbol@~3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77"
|
||||
integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=
|
||||
dependencies:
|
||||
d "1"
|
||||
es5-ext "~0.10.14"
|
||||
|
||||
event-emitter@~0.3.5:
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
|
||||
integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=
|
||||
dependencies:
|
||||
d "1"
|
||||
es5-ext "~0.10.14"
|
||||
|
||||
extend@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||
|
||||
glob-parent@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
|
||||
integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
|
||||
dependencies:
|
||||
is-glob "^3.1.0"
|
||||
path-dirname "^1.0.0"
|
||||
|
||||
glob-stream@^6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4"
|
||||
integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=
|
||||
dependencies:
|
||||
extend "^3.0.0"
|
||||
glob "^7.1.1"
|
||||
glob-parent "^3.1.0"
|
||||
is-negated-glob "^1.0.0"
|
||||
ordered-read-streams "^1.0.0"
|
||||
pumpify "^1.3.5"
|
||||
readable-stream "^2.1.5"
|
||||
remove-trailing-separator "^1.0.1"
|
||||
to-absolute-glob "^2.0.0"
|
||||
unique-stream "^2.0.2"
|
||||
|
||||
glob@^7.1.1:
|
||||
version "7.1.4"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
|
||||
integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
help-me@^1.0.1:
|
||||
"@protobufjs/inquire@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/help-me/-/help-me-1.1.0.tgz#8f2d508d0600b4a456da2f086556e7e5c056a3c6"
|
||||
integrity sha1-jy1QjQYAtKRW2i8IZVbn5cBWo8Y=
|
||||
dependencies:
|
||||
callback-stream "^1.0.2"
|
||||
glob-stream "^6.1.0"
|
||||
through2 "^2.0.1"
|
||||
xtend "^4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089"
|
||||
integrity sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
"@protobufjs/path@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d"
|
||||
integrity sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=
|
||||
|
||||
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
is-absolute@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576"
|
||||
integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==
|
||||
dependencies:
|
||||
is-relative "^1.0.0"
|
||||
is-windows "^1.0.1"
|
||||
|
||||
is-extglob@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-glob@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
|
||||
integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
|
||||
dependencies:
|
||||
is-extglob "^2.1.0"
|
||||
|
||||
is-negated-glob@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2"
|
||||
integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=
|
||||
|
||||
is-relative@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d"
|
||||
integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==
|
||||
dependencies:
|
||||
is-unc-path "^1.0.0"
|
||||
|
||||
is-unc-path@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d"
|
||||
integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==
|
||||
dependencies:
|
||||
unc-path-regex "^0.1.2"
|
||||
|
||||
is-windows@^1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
|
||||
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
|
||||
|
||||
isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
|
||||
|
||||
json-stable-stringify-without-jsonify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
|
||||
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
|
||||
|
||||
leven@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
|
||||
integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@^1.1.0, minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
||||
mqtt-packet@^6.0.0:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/mqtt-packet/-/mqtt-packet-6.1.2.tgz#239493d185c9209011a5a22ebce30e098c731f81"
|
||||
integrity sha512-yVG5PoS3wJ8TLzfS8pQMsDVLAf/EipnBAG5XQE9X/9L0EMxuduI9J2WnlRvJT497K1CUT4VJWjoP08+CKiKt1Q==
|
||||
dependencies:
|
||||
bl "^1.2.2"
|
||||
inherits "^2.0.3"
|
||||
process-nextick-args "^2.0.0"
|
||||
safe-buffer "^5.1.2"
|
||||
|
||||
mqtt@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mqtt/-/mqtt-3.0.0.tgz#7961e5f61efba3eec37d5aa9c4cbcdeb6f841380"
|
||||
integrity sha512-0nKV6MAc1ibKZwaZQUTb3iIdT4NVpj541BsYrqrGBcQdQ7Jd0MnZD1/6/nj1UFdGTboK9ZEUXvkCu2nPCugHFA==
|
||||
dependencies:
|
||||
base64-js "^1.3.0"
|
||||
commist "^1.0.0"
|
||||
concat-stream "^1.6.2"
|
||||
end-of-stream "^1.4.1"
|
||||
es6-map "^0.1.5"
|
||||
help-me "^1.0.1"
|
||||
inherits "^2.0.3"
|
||||
minimist "^1.2.0"
|
||||
mqtt-packet "^6.0.0"
|
||||
pump "^3.0.0"
|
||||
readable-stream "^2.3.6"
|
||||
reinterval "^1.1.0"
|
||||
split2 "^3.1.0"
|
||||
websocket-stream "^5.1.2"
|
||||
xtend "^4.0.1"
|
||||
|
||||
next-tick@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
|
||||
|
||||
once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
ordered-read-streams@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e"
|
||||
integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=
|
||||
dependencies:
|
||||
readable-stream "^2.0.1"
|
||||
|
||||
path-dirname@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
|
||||
integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||
|
||||
process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
|
||||
integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
|
||||
|
||||
pump@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
|
||||
integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
pump@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
|
||||
integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
|
||||
dependencies:
|
||||
end-of-stream "^1.1.0"
|
||||
once "^1.3.1"
|
||||
|
||||
pumpify@^1.3.5:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
|
||||
integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
|
||||
dependencies:
|
||||
duplexify "^3.6.0"
|
||||
inherits "^2.0.3"
|
||||
pump "^2.0.0"
|
||||
|
||||
"readable-stream@> 1.0.0 < 3.0.0", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
|
||||
integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
|
||||
dependencies:
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.3"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~2.0.0"
|
||||
safe-buffer "~5.1.1"
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.0.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
|
||||
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
|
||||
dependencies:
|
||||
inherits "^2.0.3"
|
||||
string_decoder "^1.1.1"
|
||||
util-deprecate "^1.0.1"
|
||||
|
||||
reinterval@^1.1.0:
|
||||
"@protobufjs/pool@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7"
|
||||
integrity sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54"
|
||||
integrity sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=
|
||||
|
||||
remove-trailing-separator@^1.0.1:
|
||||
"@protobufjs/utf8@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
|
||||
integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=
|
||||
|
||||
safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
split2@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/split2/-/split2-3.1.1.tgz#c51f18f3e06a8c4469aaab487687d8d956160bb6"
|
||||
integrity sha512-emNzr1s7ruq4N+1993yht631/JH+jaj0NYBosuKmLcq+JkGQ9MmTw1RB1fGaTCzUuseRIClrlSLHRNYGwWQ58Q==
|
||||
dependencies:
|
||||
readable-stream "^3.0.0"
|
||||
|
||||
stream-shift@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
|
||||
integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
|
||||
|
||||
string_decoder@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
|
||||
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
string_decoder@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
|
||||
dependencies:
|
||||
safe-buffer "~5.1.0"
|
||||
|
||||
through2-filter@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
||||
integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==
|
||||
dependencies:
|
||||
through2 "~2.0.0"
|
||||
xtend "~4.0.0"
|
||||
|
||||
through2@^2.0.1, through2@~2.0.0:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
|
||||
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
|
||||
dependencies:
|
||||
readable-stream "~2.3.6"
|
||||
xtend "~4.0.1"
|
||||
|
||||
to-absolute-glob@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b"
|
||||
integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=
|
||||
dependencies:
|
||||
is-absolute "^1.0.0"
|
||||
is-negated-glob "^1.0.0"
|
||||
|
||||
type@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/type/-/type-1.0.1.tgz#084c9a17fcc9151a2cdb1459905c2e45e4bb7d61"
|
||||
integrity sha512-MAM5dBMJCJNKs9E7JXo4CXRAansRfG0nlJxW7Wf6GZzSOvH31zClSaHdIMWLehe/EGMBkqeC55rrkaOr5Oo7Nw==
|
||||
|
||||
typedarray@^0.0.6:
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
ultron@~1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
|
||||
integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
|
||||
|
||||
unc-path-regex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
|
||||
integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
|
||||
|
||||
unique-stream@^2.0.2:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac"
|
||||
integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==
|
||||
dependencies:
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
through2-filter "^3.0.0"
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
websocket-stream@^5.1.2:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/websocket-stream/-/websocket-stream-5.5.0.tgz#9827f2846fc0d2b4dca7aab8f92980b2548b868e"
|
||||
integrity sha512-EXy/zXb9kNHI07TIMz1oIUIrPZxQRA8aeJ5XYg5ihV8K4kD1DuA+FY6R96HfdIHzlSzS8HiISAfrm+vVQkZBug==
|
||||
dependencies:
|
||||
duplexify "^3.5.1"
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.3.3"
|
||||
safe-buffer "^5.1.2"
|
||||
ws "^3.2.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
ws@^3.2.0:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
|
||||
integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
safe-buffer "~5.1.0"
|
||||
ultron "~1.1.0"
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
|
||||
"@types/long@^4.0.1":
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
|
||||
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
|
||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
|
||||
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
|
||||
|
||||
"@types/node@>=13.7.0":
|
||||
version "16.4.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.4.13.tgz#7dfd9c14661edc65cccd43a29eb454174642370d"
|
||||
integrity sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==
|
||||
|
||||
long@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||
integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==
|
||||
|
||||
protobufjs@^6.11.2:
|
||||
version "6.11.2"
|
||||
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b"
|
||||
integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==
|
||||
dependencies:
|
||||
"@protobufjs/aspromise" "^1.1.2"
|
||||
"@protobufjs/base64" "^1.1.2"
|
||||
"@protobufjs/codegen" "^2.0.4"
|
||||
"@protobufjs/eventemitter" "^1.1.0"
|
||||
"@protobufjs/fetch" "^1.1.0"
|
||||
"@protobufjs/float" "^1.0.2"
|
||||
"@protobufjs/inquire" "^1.1.0"
|
||||
"@protobufjs/path" "^1.1.2"
|
||||
"@protobufjs/pool" "^1.1.0"
|
||||
"@protobufjs/utf8" "^1.1.0"
|
||||
"@types/long" "^4.0.1"
|
||||
"@types/node" ">=13.7.0"
|
||||
long "^4.0.0"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface CallbackStore {
|
||||
wrappedCallback: any
|
||||
callback: any
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { ipcMain, ipcRenderer } from 'electron'
|
||||
|
||||
import { IpcMainEventBus } from './IpcMainEventBus'
|
||||
import { IpcRendererEventBus } from './IpcRendererEventBus'
|
||||
import { Rpc } from './Rpc'
|
||||
|
||||
export const rendererEvents = new IpcRendererEventBus(ipcRenderer)
|
||||
export const backendEvents = new IpcMainEventBus(ipcMain)
|
||||
|
||||
// Preferred way to communicate typesafe
|
||||
export const rendererRpc = new Rpc(rendererEvents)
|
||||
export const backendRpc = new Rpc(backendEvents)
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Event } from '../Events'
|
||||
|
||||
export interface EventBusInterface {
|
||||
subscribe<MessageType>(event: Event<MessageType>, callback: (msg: MessageType) => void): void
|
||||
unsubscribeAll<MessageType>(event: Event<MessageType>): void
|
||||
emit<MessageType>(event: Event<MessageType>, msg: MessageType): void
|
||||
unsubscribe<MessageType>(event: Event<MessageType>, callback: any): void
|
||||
}
|
||||
@@ -1,21 +1,8 @@
|
||||
import { IpcMain, ipcMain, ipcRenderer } from 'electron'
|
||||
import { IpcMain } from 'electron'
|
||||
import { Event } from '../Events'
|
||||
import { EventBusInterface } from './EventBusInterface'
|
||||
|
||||
import { Event } from './Events'
|
||||
import { IpcRendererEventBus } from './IpcRendererEventBus'
|
||||
|
||||
export interface EventBusInterface {
|
||||
subscribe<MessageType>(event: Event<MessageType>, callback: (msg: MessageType) => void): void
|
||||
unsubscribeAll<MessageType>(event: Event<MessageType>): void
|
||||
emit<MessageType>(event: Event<MessageType>, msg: MessageType): void
|
||||
unsubscribe<MessageType>(event: Event<MessageType>, callback: any): void
|
||||
}
|
||||
|
||||
export interface CallbackStore {
|
||||
wrappedCallback: any
|
||||
callback: any
|
||||
}
|
||||
|
||||
class IpcMainEventBus implements EventBusInterface {
|
||||
export class IpcMainEventBus implements EventBusInterface {
|
||||
private ipc: IpcMain
|
||||
private client: any
|
||||
constructor(ipc: IpcMain) {
|
||||
@@ -45,6 +32,3 @@ class IpcMainEventBus implements EventBusInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const rendererEvents = new IpcRendererEventBus(ipcRenderer)
|
||||
export const backendEvents = new IpcMainEventBus(ipcMain)
|
||||
@@ -1,26 +1,32 @@
|
||||
import { CallbackStore, EventBusInterface } from './EventBus'
|
||||
import { Event } from './Events'
|
||||
import { CallbackStore } from './CallbackStore'
|
||||
import { EventBusInterface } from './EventBusInterface'
|
||||
import { Event } from '../Events'
|
||||
import { IpcRenderer } from 'electron'
|
||||
|
||||
export class IpcRendererEventBus implements EventBusInterface {
|
||||
private ipc: IpcRenderer
|
||||
private callbacks: Array<CallbackStore> = []
|
||||
|
||||
constructor(ipc: IpcRenderer) {
|
||||
this.ipc = ipc
|
||||
}
|
||||
|
||||
public subscribe<MessageType>(event: Event<MessageType>, callback: (msg: MessageType) => void) {
|
||||
const wrappedCallback = (_: any, arg: any) => {
|
||||
callback(arg)
|
||||
}
|
||||
console.log('subscribing', event.topic)
|
||||
this.ipc.on(event.topic, wrappedCallback)
|
||||
this.callbacks.push({
|
||||
callback,
|
||||
wrappedCallback,
|
||||
})
|
||||
}
|
||||
|
||||
public unsubscribeAll<MessageType>(event: Event<MessageType>) {
|
||||
this.ipc.removeAllListeners(event.topic)
|
||||
}
|
||||
|
||||
public unsubscribe<MessageType>(event: Event<MessageType>, callback: any) {
|
||||
const item = this.callbacks.find(store => store.callback === callback)
|
||||
if (!item) {
|
||||
@@ -29,6 +35,7 @@ export class IpcRendererEventBus implements EventBusInterface {
|
||||
this.ipc.removeListener(event.topic, item.wrappedCallback)
|
||||
this.callbacks = this.callbacks.filter(a => a !== item)
|
||||
}
|
||||
|
||||
public emit<MessageType>(event: Event<MessageType>, msg: MessageType) {
|
||||
this.ipc.send(event.topic, msg)
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { Event } from '../Events'
|
||||
import { EventBusInterface } from './EventBusInterface'
|
||||
import { v4 } from 'uuid'
|
||||
|
||||
export type RpcEvent<RequestType, ResponseType> = {
|
||||
topic: string
|
||||
}
|
||||
|
||||
export class Rpc {
|
||||
constructor(private participant: EventBusInterface) {}
|
||||
|
||||
// tslint:disable-next-line:member-access
|
||||
async call<RpcRequest, RpcResponse>(
|
||||
event: RpcEvent<RpcRequest, RpcResponse>,
|
||||
request: RpcRequest,
|
||||
timeout: number = 0
|
||||
): Promise<RpcResponse> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = v4()
|
||||
|
||||
const responseEvent: Event<any> = { topic: `${event.topic}/response/${id}` }
|
||||
const requestEvent: Event<any> = { topic: `${event.topic}/request` }
|
||||
const callback = (result: { id: string; payload: RpcResponse; error: unknown }) => {
|
||||
this.participant.unsubscribe(responseEvent as any, callback)
|
||||
if (result.error) {
|
||||
reject(result.error)
|
||||
} else {
|
||||
resolve(result.payload)
|
||||
}
|
||||
console.log('received', result)
|
||||
}
|
||||
this.participant.subscribe(responseEvent, callback)
|
||||
this.participant.emit(requestEvent, { id, payload: request })
|
||||
|
||||
if (timeout > 0) {
|
||||
setTimeout(() => {
|
||||
reject(new Error(`Did not respond to ${event.topic} within ${timeout}ms`))
|
||||
this.participant.unsubscribe(responseEvent as any, callback)
|
||||
}, 10000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:member-access
|
||||
async on<RpcRequest, RpcResponse>(
|
||||
event: RpcEvent<RpcRequest, RpcResponse>,
|
||||
handler: (request: RpcRequest) => Promise<RpcResponse>
|
||||
) {
|
||||
this.participant.subscribe<RpcRequest>({ topic: `${event.topic}/request` }, async request => {
|
||||
let payload
|
||||
let error
|
||||
try {
|
||||
payload = await handler((request as any).payload)
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
const id = (request as any).id
|
||||
console.log(`${event.topic}/response/${id}`, payload, error)
|
||||
this.participant.emit({ topic: `${event.topic}/response/${id}` }, { id, payload, error })
|
||||
})
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -1,8 +1,9 @@
|
||||
import { Base64Message } from '../backend/src/Model/Base64Message'
|
||||
import { DataSourceState, MqttOptions } from '../backend/src/DataSource'
|
||||
import { UpdateInfo } from 'builder-util-runtime'
|
||||
import { RpcEvent } from './EventSystem/Rpc'
|
||||
|
||||
export interface Event<MessageType> {
|
||||
export type Event<MessageType> = {
|
||||
topic: string
|
||||
}
|
||||
|
||||
@@ -49,3 +50,7 @@ export function makeConnectionMessageEvent(connectionId: string): Event<MqttMess
|
||||
topic: `conn/${connectionId}`,
|
||||
}
|
||||
}
|
||||
|
||||
export const getAppVersion: RpcEvent<void, string> = {
|
||||
topic: 'getAppVersion',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { OpenDialogOptions, OpenDialogReturnValue } from 'electron'
|
||||
import { RpcEvent } from './EventSystem/Rpc'
|
||||
|
||||
export function makeOpenDialogRpc(): RpcEvent<OpenDialogOptions, OpenDialogReturnValue> {
|
||||
return {
|
||||
topic: 'openDialog',
|
||||
}
|
||||
}
|
||||
+8
-25
@@ -1,39 +1,22 @@
|
||||
import { Event } from './'
|
||||
import { RpcEvent } from './EventSystem/Rpc'
|
||||
|
||||
interface StorageEvent {
|
||||
transactionId: string
|
||||
export interface StoreCommand {
|
||||
store: string
|
||||
data: any
|
||||
}
|
||||
|
||||
export interface StoreCommand extends StorageEvent {
|
||||
store?: string
|
||||
data?: any
|
||||
error?: any
|
||||
}
|
||||
|
||||
export interface LoadCommand extends StorageEvent {
|
||||
export interface LoadCommand {
|
||||
store: string
|
||||
}
|
||||
|
||||
export const storageStoreEvent: Event<StoreCommand> = {
|
||||
export const storageStoreEvent: RpcEvent<StoreCommand, void> = {
|
||||
topic: 'storage/store',
|
||||
}
|
||||
|
||||
export const storageLoadEvent: Event<LoadCommand> = {
|
||||
export const storageLoadEvent: RpcEvent<LoadCommand, StoreCommand> = {
|
||||
topic: 'storage/load',
|
||||
}
|
||||
|
||||
export function makeStorageAcknowledgementEvent(transactionId: string): Event<StoreCommand> {
|
||||
return {
|
||||
topic: `storage/ack/${transactionId}`,
|
||||
}
|
||||
}
|
||||
|
||||
export function makeStorageResponseEvent(transactionId: string): Event<StoreCommand> {
|
||||
return {
|
||||
topic: `storage/response/${transactionId}`,
|
||||
}
|
||||
}
|
||||
|
||||
export const storageClearEvent: Event<StorageEvent> = {
|
||||
export const storageClearEvent: RpcEvent<void, void> = {
|
||||
topic: 'storage/clear',
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
export * from './Events'
|
||||
export * from './EventDispatcher'
|
||||
export * from './EventBus'
|
||||
export * from './EventSystem/EventDispatcher'
|
||||
export * from './EventSystem/EventBus'
|
||||
export * from './EventSystem/EventBusInterface'
|
||||
|
||||
+27
-20
@@ -3,6 +3,9 @@
|
||||
"version": "0.4.0-beta1",
|
||||
"description": "Explore your message queues",
|
||||
"main": "dist/src/electron.js",
|
||||
"engines": {
|
||||
"node": "19"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
"test": "yarn test:app && yarn test:backend",
|
||||
@@ -12,8 +15,9 @@
|
||||
"dev": "npm-run-all --parallel dev:*",
|
||||
"dev:app": "cd app && npm run dev",
|
||||
"dev:electron": "tsc && electron . --development",
|
||||
"lint": "npm-run-all --parallel lint:prettier lint:tslint lint:spellcheck",
|
||||
"lint": "npm-run-all --parallel lint:prettier lint:tslint",
|
||||
"lint:prettier": "prettier --check \"**/*.ts{x,}\"",
|
||||
"lint:prettier:fix": "prettier --write \"**/*.ts{x,}\"",
|
||||
"lint:tslint": "tslint -p ./",
|
||||
"lint:spellcheck": "cspell -e ./build -e \"node_modules\" \"**/*.ts{x,}\"",
|
||||
"build": "tsc && cd app && yarn run build && cd ..",
|
||||
@@ -34,6 +38,7 @@
|
||||
"mac": {
|
||||
"appId": "de.t7n.apps.mqtt-explorer",
|
||||
"category": "public.app-category.developer-tools",
|
||||
"hardenedRuntime": true,
|
||||
"publish": [
|
||||
"github"
|
||||
],
|
||||
@@ -68,6 +73,8 @@
|
||||
"homepage": "https://github.com",
|
||||
"license": "CC-BY-ND-4.0",
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "^7.17.2",
|
||||
"@electron/notarize": "^2.3.0",
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/fs-extra": "8",
|
||||
"@types/lowdb": "^1.0.6",
|
||||
@@ -77,43 +84,43 @@
|
||||
"@types/node": "^12.6.8",
|
||||
"@types/semver": "7",
|
||||
"@types/sha1": "^1.1.1",
|
||||
"builder-util-runtime": "^8.2.5",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"builder-util-runtime": "^9",
|
||||
"chai": "^4.2.0",
|
||||
"cspell": "^4.0.28",
|
||||
"electron": "8.2.3",
|
||||
"electron-builder": "22.5.1",
|
||||
"electron": "29.1.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"mocha": "7.1",
|
||||
"mustache": "4",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "15",
|
||||
"prettier": "2",
|
||||
"prettier": "^3.2.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"source-map-support": "^0.5.9",
|
||||
"spectron": "10",
|
||||
"ts-node": "^8.2.0",
|
||||
"tslint": "6",
|
||||
"tslint-config-airbnb": "^5.11.1",
|
||||
"tslint-react": "^4.0.0",
|
||||
"spectron": "19",
|
||||
"ts-node": "^10.9.2",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-airbnb": "^5.11.2",
|
||||
"tslint-react": "^5.0.0",
|
||||
"tslint-react-recommended": "^1.0.15",
|
||||
"tslint-strict-null-checks": "^1.0.1",
|
||||
"typescript": "^3.2.2",
|
||||
"webdriverio": "6"
|
||||
"typescript": "^4.5.5",
|
||||
"webdriverio": "7.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"about-window": "^1.12.1",
|
||||
"axios": "^0.19.0",
|
||||
"dot-prop": "^5.0.0",
|
||||
"electron-log": "4.1.1",
|
||||
"electron-telemetry": "git+https://github.com/thomasnordquist/electron-telemetry.git#dist",
|
||||
"electron-updater": "^4.0.6",
|
||||
"electron-log": "4.4.6",
|
||||
"electron-updater": "^4.6",
|
||||
"fs-extra": "9",
|
||||
"js-base64": "^2.5.1",
|
||||
"js-base64": "^3.7.2",
|
||||
"json-to-ast": "^2.1.0",
|
||||
"lowdb": "^1.0.0",
|
||||
"mime": "^2.4.4",
|
||||
"mqtt": "^3.0.0",
|
||||
"mqtt": "^4.3.6",
|
||||
"protobufjs": "~6.11.2",
|
||||
"sha1": "^1.1.1",
|
||||
"uuid": "^8.3.2",
|
||||
"yarn-run-all": "^3.1.1"
|
||||
},
|
||||
"optionalDependencies": {}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -5,7 +5,16 @@ import * as dotProp from 'dot-prop'
|
||||
|
||||
const linuxAppImage: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: true,
|
||||
ia32: false,
|
||||
armv7l: true,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
publish: 'always',
|
||||
}
|
||||
|
||||
const linuxDeb: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: false,
|
||||
armv7l: true,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
@@ -23,7 +32,7 @@ const linuxSnap: builder.CliOptions = {
|
||||
|
||||
const winPortable: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: true,
|
||||
ia32: false,
|
||||
armv7l: false,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
@@ -32,7 +41,7 @@ const winPortable: builder.CliOptions = {
|
||||
|
||||
const winNsis: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: true,
|
||||
ia32: false,
|
||||
armv7l: false,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
@@ -41,7 +50,7 @@ const winNsis: builder.CliOptions = {
|
||||
|
||||
const winAppx: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: true,
|
||||
ia32: false,
|
||||
armv7l: false,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
@@ -50,7 +59,7 @@ const winAppx: builder.CliOptions = {
|
||||
|
||||
const mac: builder.CliOptions = {
|
||||
x64: true,
|
||||
ia32: true,
|
||||
ia32: false,
|
||||
armv7l: false,
|
||||
arm64: false,
|
||||
projectDir: './build/clean',
|
||||
@@ -69,6 +78,7 @@ async function executeBuild() {
|
||||
case 'linux':
|
||||
await buildWithOptions(linuxAppImage, { platform: 'linux', package: 'AppImage' })
|
||||
await buildWithOptions(linuxSnap, { platform: 'linux', package: 'snap' })
|
||||
await buildWithOptions(linuxDeb, { platform: 'linux', package: 'deb' })
|
||||
break
|
||||
case 'mac':
|
||||
await buildWithOptions(mac, { platform: 'mac', package: 'dmg' })
|
||||
|
||||
@@ -8,5 +8,11 @@
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
syntax = "proto2";
|
||||
|
||||
//
|
||||
// To compile:
|
||||
// cd client_libraries/java
|
||||
// protoc --proto_path=../../ --java_out=src/main/java ../../sparkplug_b.proto
|
||||
//
|
||||
package com.cirruslink.sparkplug.protobuf;
|
||||
|
||||
option java_package = "com.cirruslink.sparkplug.protobuf";
|
||||
option java_outer_classname = "SparkplugBProto";
|
||||
|
||||
message Payload {
|
||||
/*
|
||||
// Indexes of Data Types
|
||||
|
||||
// Unknown placeholder for future expansion.
|
||||
Unknown = 0;
|
||||
|
||||
// Basic Types
|
||||
Int8 = 1;
|
||||
Int16 = 2;
|
||||
Int32 = 3;
|
||||
Int64 = 4;
|
||||
UInt8 = 5;
|
||||
UInt16 = 6;
|
||||
UInt32 = 7;
|
||||
UInt64 = 8;
|
||||
Float = 9;
|
||||
Double = 10;
|
||||
Boolean = 11;
|
||||
String = 12;
|
||||
DateTime = 13;
|
||||
Text = 14;
|
||||
|
||||
// Additional Metric Types
|
||||
UUID = 15;
|
||||
DataSet = 16;
|
||||
Bytes = 17;
|
||||
File = 18;
|
||||
Template = 19;
|
||||
|
||||
// Additional PropertyValue Types
|
||||
PropertySet = 20;
|
||||
PropertySetList = 21;
|
||||
|
||||
*/
|
||||
|
||||
message Template {
|
||||
|
||||
message Parameter {
|
||||
optional string name = 1;
|
||||
optional uint32 type = 2;
|
||||
|
||||
oneof value {
|
||||
uint32 int_value = 3;
|
||||
uint64 long_value = 4;
|
||||
float float_value = 5;
|
||||
double double_value = 6;
|
||||
bool boolean_value = 7;
|
||||
string string_value = 8;
|
||||
ParameterValueExtension extension_value = 9;
|
||||
}
|
||||
|
||||
message ParameterValueExtension {
|
||||
extensions 1 to max;
|
||||
}
|
||||
}
|
||||
|
||||
optional string version = 1; // The version of the Template to prevent mismatches
|
||||
repeated Metric metrics = 2; // Each metric is the name of the metric and the datatype of the member but does not contain a value
|
||||
repeated Parameter parameters = 3;
|
||||
optional string template_ref = 4; // Reference to a template if this is extending a Template or an instance - must exist if an instance
|
||||
optional bool is_definition = 5;
|
||||
extensions 6 to max;
|
||||
}
|
||||
|
||||
message DataSet {
|
||||
|
||||
message DataSetValue {
|
||||
|
||||
oneof value {
|
||||
uint32 int_value = 1;
|
||||
uint64 long_value = 2;
|
||||
float float_value = 3;
|
||||
double double_value = 4;
|
||||
bool boolean_value = 5;
|
||||
string string_value = 6;
|
||||
DataSetValueExtension extension_value = 7;
|
||||
}
|
||||
|
||||
message DataSetValueExtension {
|
||||
extensions 1 to max;
|
||||
}
|
||||
}
|
||||
|
||||
message Row {
|
||||
repeated DataSetValue elements = 1;
|
||||
extensions 2 to max; // For third party extensions
|
||||
}
|
||||
|
||||
optional uint64 num_of_columns = 1;
|
||||
repeated string columns = 2;
|
||||
repeated uint32 types = 3;
|
||||
repeated Row rows = 4;
|
||||
extensions 5 to max; // For third party extensions
|
||||
}
|
||||
|
||||
message PropertyValue {
|
||||
|
||||
optional uint32 type = 1;
|
||||
optional bool is_null = 2;
|
||||
|
||||
oneof value {
|
||||
uint32 int_value = 3;
|
||||
uint64 long_value = 4;
|
||||
float float_value = 5;
|
||||
double double_value = 6;
|
||||
bool boolean_value = 7;
|
||||
string string_value = 8;
|
||||
PropertySet propertyset_value = 9;
|
||||
PropertySetList propertysets_value = 10; // List of Property Values
|
||||
PropertyValueExtension extension_value = 11;
|
||||
}
|
||||
|
||||
message PropertyValueExtension {
|
||||
extensions 1 to max;
|
||||
}
|
||||
}
|
||||
|
||||
message PropertySet {
|
||||
repeated string keys = 1; // Names of the properties
|
||||
repeated PropertyValue values = 2;
|
||||
extensions 3 to max;
|
||||
}
|
||||
|
||||
message PropertySetList {
|
||||
repeated PropertySet propertyset = 1;
|
||||
extensions 2 to max;
|
||||
}
|
||||
|
||||
message MetaData {
|
||||
// Bytes specific metadata
|
||||
optional bool is_multi_part = 1;
|
||||
|
||||
// General metadata
|
||||
optional string content_type = 2; // Content/Media type
|
||||
optional uint64 size = 3; // File size, String size, Multi-part size, etc
|
||||
optional uint64 seq = 4; // Sequence number for multi-part messages
|
||||
|
||||
// File metadata
|
||||
optional string file_name = 5; // File name
|
||||
optional string file_type = 6; // File type (i.e. xml, json, txt, cpp, etc)
|
||||
optional string md5 = 7; // md5 of data
|
||||
|
||||
// Catchalls and future expansion
|
||||
optional string description = 8; // Could be anything such as json or xml of custom properties
|
||||
extensions 9 to max;
|
||||
}
|
||||
|
||||
message Metric {
|
||||
|
||||
optional string name = 1; // Metric name - should only be included on birth
|
||||
optional uint64 alias = 2; // Metric alias - tied to name on birth and included in all later DATA messages
|
||||
optional uint64 timestamp = 3; // Timestamp associated with data acquisition time
|
||||
optional uint32 datatype = 4; // DataType of the metric/tag value
|
||||
optional bool is_historical = 5; // If this is historical data and should not update real time tag
|
||||
optional bool is_transient = 6; // Tells consuming clients such as MQTT Engine to not store this as a tag
|
||||
optional bool is_null = 7; // If this is null - explicitly say so rather than using -1, false, etc for some datatypes.
|
||||
optional MetaData metadata = 8; // Metadata for the payload
|
||||
optional PropertySet properties = 9;
|
||||
|
||||
oneof value {
|
||||
uint32 int_value = 10;
|
||||
uint64 long_value = 11;
|
||||
float float_value = 12;
|
||||
double double_value = 13;
|
||||
bool boolean_value = 14;
|
||||
string string_value = 15;
|
||||
bytes bytes_value = 16; // Bytes, File
|
||||
DataSet dataset_value = 17;
|
||||
Template template_value = 18;
|
||||
MetricValueExtension extension_value = 19;
|
||||
}
|
||||
|
||||
message MetricValueExtension {
|
||||
extensions 1 to max;
|
||||
}
|
||||
}
|
||||
|
||||
optional uint64 timestamp = 1; // Timestamp at message sending time
|
||||
repeated Metric metrics = 2; // Repeated forever - no limit in Google Protobufs
|
||||
optional uint64 seq = 3; // Sequence number
|
||||
optional string uuid = 4; // UUID to track message type in terms of schema definitions
|
||||
optional bytes body = 5; // To optionally bypass the whole definition above
|
||||
extensions 6 to max; // For third party extensions
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as fs from 'fs-extra'
|
||||
import * as path from 'path'
|
||||
import { chdir } from 'process'
|
||||
import { exec } from './util'
|
||||
|
||||
|
||||
@@ -53,12 +53,12 @@ async function uploadAsset() {
|
||||
try {
|
||||
uploadUrl = await createDraft(tag)
|
||||
} catch (error) {
|
||||
console.error('failed to create draft', error.stack)
|
||||
console.error('failed to create draft', (error as Error).stack)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('failed to find tag release', error.stack)
|
||||
console.error('failed to find tag release', (error as Error).stack)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ function redirectOutputFor(child: ChildProcess) {
|
||||
}
|
||||
|
||||
async function waitFor(child: ChildProcess) {
|
||||
return new Promise(resolve => {
|
||||
return new Promise<void>(resolve => {
|
||||
child.once('close', () => resolve())
|
||||
})
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { autoUpdater, UpdateInfo } from 'electron-updater'
|
||||
import { BuildInfo } from 'electron-telemetry/build/Model'
|
||||
// import { BuildInfo } from 'electron-telemetry/build/Model'
|
||||
|
||||
export function shouldAutoUpdate(build: BuildInfo) {
|
||||
export function shouldAutoUpdate(build: any) {
|
||||
return (
|
||||
build.package !== 'portable' &&
|
||||
build.package !== 'appx' &&
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import { BuildInfo } from 'electron-telemetry/build/Model'
|
||||
// import { BuildInfo } from 'electron-telemetry/build/Model'
|
||||
|
||||
let buildOptions: BuildInfo = {
|
||||
let buildOptions: any = {
|
||||
platform: process.platform,
|
||||
package: 'unpacked',
|
||||
} as any
|
||||
|
||||
+15
-5
@@ -1,23 +1,31 @@
|
||||
import * as log from 'electron-log'
|
||||
import * as path from 'path'
|
||||
import ConfigStorage from '../backend/src/ConfigStorage'
|
||||
import { app, BrowserWindow, Menu } from 'electron'
|
||||
import { app, BrowserWindow, Menu, dialog } from 'electron'
|
||||
import { autoUpdater } from 'electron-updater'
|
||||
import { ConnectionManager } from '../backend/src/index'
|
||||
import { electronTelemetryFactory } from 'electron-telemetry'
|
||||
// import { electronTelemetryFactory } from 'electron-telemetry'
|
||||
import { menuTemplate } from './MenuTemplate'
|
||||
import buildOptions from './buildOptions'
|
||||
import { waitForDevServer, isDev, runningUiTestOnCi, loadDevTools } from './development'
|
||||
import { shouldAutoUpdate, handleAutoUpdate } from './autoUpdater'
|
||||
import { registerCrashReporter } from './registerCrashReporter'
|
||||
import { makeOpenDialogRpc } from '../events/OpenDialogRequest'
|
||||
import { backendRpc, getAppVersion } from '../events'
|
||||
|
||||
registerCrashReporter()
|
||||
|
||||
if (!isDev() && !runningUiTestOnCi()) {
|
||||
const electronTelemetry = electronTelemetryFactory('9b0c8ca04a361eb8160d98c5', buildOptions)
|
||||
}
|
||||
// if (!isDev() && !runningUiTestOnCi()) {
|
||||
// const electronTelemetry = electronTelemetryFactory('9b0c8ca04a361eb8160d98c5', buildOptions)
|
||||
// }
|
||||
|
||||
app.commandLine.appendSwitch('--no-sandbox')
|
||||
app.whenReady().then(() => {
|
||||
backendRpc.on(makeOpenDialogRpc(), async request => {
|
||||
return dialog.showOpenDialog(BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0], request)
|
||||
})
|
||||
backendRpc.on(getAppVersion, async () => app.getVersion())
|
||||
})
|
||||
|
||||
autoUpdater.logger = log
|
||||
log.info('App starting...')
|
||||
@@ -45,6 +53,8 @@ async function createWindow() {
|
||||
height: 720,
|
||||
show: false,
|
||||
webPreferences: {
|
||||
...({ enableRemoteModule: true } as any),
|
||||
contextIsolation: false,
|
||||
nodeIntegration: true,
|
||||
devTools: true,
|
||||
sandbox: false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn, expandTopic, moveToCenterOfElement, sleep, writeText } from '../util'
|
||||
|
||||
export async function clearOldTopics(browser: Browser) {
|
||||
export async function clearOldTopics(browser: Browser<'async'>) {
|
||||
const topics = ['hello', 'test 123']
|
||||
for (const topic of topics) {
|
||||
await expandTopic(topic, browser)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn, setTextInInput } from '../util'
|
||||
|
||||
export async function connectTo(host: string, browser: Browser) {
|
||||
export async function connectTo(host: string, browser: Browser<'async'>) {
|
||||
await setTextInInput('Host', host, browser)
|
||||
|
||||
await browser.saveScreenshot('screen1.png')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyTopicToClipboard(browser: Browser) {
|
||||
export async function copyTopicToClipboard(browser: Browser<'async'>) {
|
||||
const copyButton = await browser.$('//span[contains(text(), "Topic")]//button')
|
||||
await clickOn(copyButton, browser, 1)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyValueToClipboard(browser: Browser) {
|
||||
export async function copyValueToClipboard(browser: Browser<'async'>) {
|
||||
const copyButton = await browser.$('//span[contains(text(), "Value")]//button')
|
||||
await clickOn(copyButton, browser, 1)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function disconnect(browser: Browser) {
|
||||
export async function disconnect(browser: Browser<'async'>) {
|
||||
const disconnectButton = await browser.$('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton, browser)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
showText,
|
||||
} from '../util'
|
||||
|
||||
export async function publishTopic(browser: Browser) {
|
||||
export async function publishTopic(browser: Browser<'async'>) {
|
||||
await expandTopic('kitchen/lamp/state', browser)
|
||||
const topicInput = await browser.$('//input[contains(@value,"kitchen/lamp/state")][1]')
|
||||
await clickOn(topicInput, browser)
|
||||
@@ -17,8 +17,7 @@ export async function publishTopic(browser: Browser) {
|
||||
await writeText('set', browser, 300)
|
||||
|
||||
const payloadInput = await browser.$('//*[contains(@class, "ace_text-input")]')
|
||||
await writeTextPayload(payloadInput, '{"action": "setState", "state": "on" }')
|
||||
|
||||
await writeTextPayload(payloadInput, 'off')
|
||||
await sleep(500)
|
||||
const formatJsonButton = await browser.$('#sidebar-publish-format-json')
|
||||
await clickOn(formatJsonButton, browser)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function reconnect(browser: Browser) {
|
||||
export async function reconnect(browser: Browser<'async'>) {
|
||||
const disconnectButton = await browser.$('//button/span[contains(text(),"Disconnect")]')
|
||||
await clickOn(disconnectButton, browser)
|
||||
const connectButton = await browser.$('//button/span[contains(text(),"Connect")]')
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn, deleteTextWithBackspaces, showText, sleep, writeText } from '../util'
|
||||
|
||||
export async function searchTree(text: string, browser: Browser) {
|
||||
export async function searchTree(text: string, browser: Browser<'async'>) {
|
||||
const searchField = await browser.$('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, browser, 1)
|
||||
await writeText(text, browser, 100)
|
||||
await sleep(1500)
|
||||
}
|
||||
|
||||
export async function clearSearch(browser: Browser) {
|
||||
export async function clearSearch(browser: Browser<'async'>) {
|
||||
const searchField = await browser.$('//input[contains(@placeholder, "Search")]')
|
||||
await clickOn(searchField, browser, 1)
|
||||
await deleteTextWithBackspaces(searchField, browser, 100)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { clickOn, sleep, setInputText } from '../util'
|
||||
|
||||
export async function showAdvancedConnectionSettings(browser: Browser) {
|
||||
export async function showAdvancedConnectionSettings(browser: Browser<'async'>) {
|
||||
const advancedSettingsButton = await browser.$('//button/span[contains(text(),"Advanced")]')
|
||||
const addButton = await browser.$('//button/span[contains(text(),"Add")]')
|
||||
const topicInput = await browser.$('//*[contains(@class, "advanced-connection-settings-topic-input")]//input')
|
||||
@@ -24,7 +24,7 @@ export async function showAdvancedConnectionSettings(browser: Browser) {
|
||||
await clickOn(connectButton, browser)
|
||||
}
|
||||
|
||||
async function deleteFirstSubscribedTopic(browser: Browser) {
|
||||
async function deleteFirstSubscribedTopic(browser: Browser<'async'>) {
|
||||
const deleteButton = await browser.$('.advanced-connection-settings-topic-list button')
|
||||
await clickOn(deleteButton, browser)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { expandTopic, sleep } from '../util'
|
||||
|
||||
export async function showJsonPreview(browser: Browser) {
|
||||
export async function showJsonPreview(browser: Browser<'async'>) {
|
||||
await expandTopic('actuality/showcase', browser)
|
||||
await browser.saveScreenshot('screen3.png')
|
||||
await sleep(1000)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser } from 'webdriverio'
|
||||
import { clickOn, showText, sleep } from '../util'
|
||||
|
||||
export async function showMenu(browser: Browser) {
|
||||
export async function showMenu(browser: Browser<'async'>) {
|
||||
const menuButton = await browser.$('//button[contains(@aria-label, "Menu")]')
|
||||
await clickOn(menuButton, browser)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { moveToCenterOfElement, clickOn, clickOnHistory, expandTopic, sleep, writeText } from '../util'
|
||||
|
||||
export async function showNumericPlot(browser: Browser) {
|
||||
export async function showNumericPlot(browser: Browser<'async'>) {
|
||||
await expandTopic('kitchen/coffee_maker', browser)
|
||||
let heater = await valuePreviewGuttersShowChartIcon('heater', browser)
|
||||
await moveToCenterOfElement(heater, browser)
|
||||
@@ -42,7 +42,7 @@ export async function showNumericPlot(browser: Browser) {
|
||||
await clickOnHistory(browser)
|
||||
}
|
||||
|
||||
async function valuePreviewGuttersShowChartIcon(name: string, browser: Browser) {
|
||||
async function valuePreviewGuttersShowChartIcon(name: string, browser: Browser<'async'>) {
|
||||
for (let retries = 0; retries < 2; retries += 1) {
|
||||
try {
|
||||
return await browser.$(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
@@ -53,23 +53,23 @@ async function valuePreviewGuttersShowChartIcon(name: string, browser: Browser)
|
||||
return browser.$(`//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "${name}")]`)
|
||||
}
|
||||
|
||||
async function chartSettings(name: string, browser: Browser) {
|
||||
async function chartSettings(name: string, browser: Browser<'async'>) {
|
||||
const settings = await browser.$(`//*[contains(@data-test-type, "ChartSettings")][contains(@data-test, "${name}")]`)
|
||||
return clickOn(settings, browser)
|
||||
}
|
||||
|
||||
async function clickAway(name: string, browser: Browser) {
|
||||
async function clickAway(name: string, browser: Browser<'async'>) {
|
||||
const settings = await browser.$(`//*[contains(@data-test-type, "ChartPaper")][contains(@data-test, "${name}")]`)
|
||||
await moveToCenterOfElement(settings, browser)
|
||||
await browser.keys(['Escape'])
|
||||
}
|
||||
|
||||
async function removeChart(name: string, browser: Browser) {
|
||||
async function removeChart(name: string, browser: Browser<'async'>) {
|
||||
const remove = await browser.$(`//*[contains(@data-test-type, "RemoveChart")][contains(@data-test, "${name}")]`)
|
||||
return clickOn(remove, browser)
|
||||
}
|
||||
|
||||
async function clickOnMenuPoint(name: string, browser: Browser) {
|
||||
async function clickOnMenuPoint(name: string, browser: Browser<'async'>) {
|
||||
const item = await browser.$(`//li/span[contains(text(), "${name}")]`)
|
||||
return clickOn(item, browser)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Browser, Element } from 'webdriverio'
|
||||
import { clickOn, showText, sleep } from '../util'
|
||||
|
||||
// Expects a topic with at least two messages to be selected
|
||||
export async function showOffDiffCapability(browser: Browser) {
|
||||
export async function showOffDiffCapability(browser: Browser<'async'>) {
|
||||
await showText('Compare messages', 2000, browser, 'top')
|
||||
|
||||
await showText('Show raw message', 2000, browser, 'bottom')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
import { showKeys, showText, sleep } from '../util'
|
||||
|
||||
export async function showZoomLevel(browser: Browser) {
|
||||
export async function showZoomLevel(browser: Browser<'async'>) {
|
||||
await showKeys('Zoom in', 2000, browser, 'top', ['Ctrl', '+'])
|
||||
await sleep(2000)
|
||||
await showKeys('Zoom out', 2000, browser, 'middle', ['Ctrl', '-'])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { clickOn } from './'
|
||||
import { Browser, Element } from 'webdriverio'
|
||||
|
||||
export async function expandTopic(path: string, browser: Browser) {
|
||||
export async function expandTopic(path: string, browser: Browser<'async'>) {
|
||||
const originalTopics = path.split('/')
|
||||
let topics = path.split('/')
|
||||
while (topics.length > 0 && !(await topicMatches(topics, browser))) {
|
||||
@@ -18,7 +18,7 @@ export async function expandTopic(path: string, browser: Browser) {
|
||||
}
|
||||
}
|
||||
|
||||
async function topicMatches(topics: Array<string>, browser: Browser) {
|
||||
async function topicMatches(topics: Array<string>, browser: Browser<'async'>) {
|
||||
const result = await browser.$(topicSelector(topics))
|
||||
return result.isExisting()
|
||||
}
|
||||
|
||||
+17
-12
@@ -18,7 +18,7 @@ export function sleep(ms: number, required = false) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function writeText(text: string, browser: Browser, delay = 0) {
|
||||
export async function writeText(text: string, browser: Browser<'async'>, delay = 0) {
|
||||
if (fast) {
|
||||
return browser.keys(text.split(''))
|
||||
}
|
||||
@@ -29,7 +29,12 @@ export async function writeText(text: string, browser: Browser, delay = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteTextWithBackspaces(element: Element, browser: Browser, delay = 0, count = 0) {
|
||||
export async function deleteTextWithBackspaces(
|
||||
element: Element<'async'>,
|
||||
browser: Browser<'async'>,
|
||||
delay = 0,
|
||||
count = 0
|
||||
) {
|
||||
const length = count > 0 ? count : (await element.getValue()).length
|
||||
for (let i = 0; i < length; i += 1) {
|
||||
await browser.keys(['Backspace'])
|
||||
@@ -37,13 +42,13 @@ export async function deleteTextWithBackspaces(element: Element, browser: Browse
|
||||
}
|
||||
}
|
||||
|
||||
export async function setInputText(input: Element, text: string, browser: Browser) {
|
||||
export async function setInputText(input: Element<'async'>, text: string, browser: Browser<'async'>) {
|
||||
await clickOn(input, browser, 1)
|
||||
await deleteTextWithBackspaces(input, browser)
|
||||
await input.setValue(text)
|
||||
}
|
||||
|
||||
export async function setTextInInput(name: string, text: string, browser: Browser) {
|
||||
export async function setTextInInput(name: string, text: string, browser: Browser<'async'>) {
|
||||
const input = await browser.$(`//label[contains(text(), "${name}")]/..//input`)
|
||||
await clickOn(input, browser, 1)
|
||||
await browser.$(`//label[contains(text(), "${name}")]/..//input`)
|
||||
@@ -52,7 +57,7 @@ export async function setTextInInput(name: string, text: string, browser: Browse
|
||||
await input.setValue(text)
|
||||
}
|
||||
|
||||
export async function moveToCenterOfElement(element: Element, browser: Browser) {
|
||||
export async function moveToCenterOfElement(element: Element<'async'>, browser: Browser<'async'>) {
|
||||
const { x, y } = await element.getLocation()
|
||||
const { width, height } = await element.getSize()
|
||||
|
||||
@@ -69,12 +74,12 @@ export async function moveToCenterOfElement(element: Element, browser: Browser)
|
||||
await element.moveTo()
|
||||
}
|
||||
|
||||
export async function clickOnHistory(browser: Browser) {
|
||||
export async function clickOnHistory(browser: Browser<'async'>) {
|
||||
const messageHistory = await browser.$('//span/*[contains(text(), "History")]')
|
||||
await clickOn(messageHistory, browser)
|
||||
}
|
||||
|
||||
export async function clickOn(element: Element, browser: Browser, clicks = 1) {
|
||||
export async function clickOn(element: Element<'async'>, browser: Browser<'async'>, clicks = 1) {
|
||||
await moveToCenterOfElement(element, browser)
|
||||
for (let i = 0; i < clicks; i += 1) {
|
||||
await element.click()
|
||||
@@ -82,7 +87,7 @@ export async function clickOn(element: Element, browser: Browser, clicks = 1) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function createFakeMousePointer(browser: Browser) {
|
||||
export async function createFakeMousePointer(browser: Browser<'async'>) {
|
||||
const js = 'window.demo.enableMouse();'
|
||||
|
||||
await browser.execute(js)
|
||||
@@ -91,7 +96,7 @@ export async function createFakeMousePointer(browser: Browser) {
|
||||
export async function showText(
|
||||
text: string,
|
||||
duration: number = 0,
|
||||
browser: Browser,
|
||||
browser: Browser<'async'>,
|
||||
location: 'top' | 'bottom' | 'middle' = 'bottom',
|
||||
keys = []
|
||||
) {
|
||||
@@ -102,7 +107,7 @@ export async function showText(
|
||||
|
||||
type HeapDump = any
|
||||
|
||||
export async function getHeapDump(browser: Browser): Promise<HeapDump> {
|
||||
export async function getHeapDump(browser: Browser<'async'>): Promise<HeapDump> {
|
||||
const filename = 'heapdump.json'
|
||||
const js = `window.demo.writeHeapdump('${filename}');`
|
||||
await browser.execute(js)
|
||||
@@ -125,7 +130,7 @@ export async function countInstancesOf(heapDump: HeapDump, className: ClassNameM
|
||||
export async function showKeys(
|
||||
text: string,
|
||||
duration: number = 0,
|
||||
browser: Browser,
|
||||
browser: Browser<'async'>,
|
||||
location: 'top' | 'bottom' | 'middle' = 'bottom',
|
||||
keys: Array<string> = []
|
||||
) {
|
||||
@@ -134,7 +139,7 @@ export async function showKeys(
|
||||
await browser.execute(js)
|
||||
}
|
||||
|
||||
export async function hideText(browser: Browser) {
|
||||
export async function hideText(browser: Browser<'async'>) {
|
||||
const js = 'window.demo.hideMessage();'
|
||||
await browser.execute(js)
|
||||
await sleep(600)
|
||||
|
||||
+12
-3
@@ -8,9 +8,15 @@
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"sourceRoot": "src/",
|
||||
"lib": ["es2017", "dom"],
|
||||
"lib": [
|
||||
"es2017",
|
||||
"dom"
|
||||
],
|
||||
"sourceMap": true,
|
||||
"types": ["node"]
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": [
|
||||
"src/electron.ts",
|
||||
@@ -18,5 +24,8 @@
|
||||
"src/spec/demoVideo.ts",
|
||||
"src/spec/leakTest.ts",
|
||||
"scripts/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user