From 6c5c1b8cb855ef812e8d1728c9ef73a762442960 Mon Sep 17 00:00:00 2001
From: Lars Berning <151194+laberning@users.noreply.github.com>
Date: Sat, 13 Mar 2021 19:20:36 +0000
Subject: [PATCH] adds linting pre commit hook, cleans documentation
---
.gitignore | 4 +-
.husky/.gitignore | 1 +
.husky/pre-commit | 4 +
.markdownlint.json | 4 +
README.md | 4 +-
app/ble/RowingMachinePeripheral.js | 1 -
app/client/app.js | 5 +-
app/server.js | 2 +-
doc/attribution.md | 4 +-
doc/backlog.md | 11 ++-
doc/installation.md | 8 +-
package-lock.json | 154 +++++++++++++++++++++++++++--
package.json | 7 +-
13 files changed, 184 insertions(+), 25 deletions(-)
create mode 100644 .husky/.gitignore
create mode 100755 .husky/pre-commit
create mode 100644 .markdownlint.json
diff --git a/.gitignore b/.gitignore
index 20ea6b8..2eb535f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -70,7 +70,9 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
+.vscode
+
node_modules
.DS_Store
._*
-tmp/
\ No newline at end of file
+tmp/
diff --git a/.husky/.gitignore b/.husky/.gitignore
new file mode 100644
index 0000000..31354ec
--- /dev/null
+++ b/.husky/.gitignore
@@ -0,0 +1 @@
+_
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 0000000..20d0d06
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+npm run lint
diff --git a/.markdownlint.json b/.markdownlint.json
new file mode 100644
index 0000000..b077f0e
--- /dev/null
+++ b/.markdownlint.json
@@ -0,0 +1,4 @@
+{
+ "default": true,
+ "MD013": false
+}
diff --git a/README.md b/README.md
index d328273..9b747ce 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ Open Rowing Monitor implements a physics model to simulate the typical metrics o
### Web Interface
-The web interface visualizes the rowing metrics on any device that can run a browser (i.e. a smartphone that you attach to your rowing machine while training). It uses websockets to show the rowing status in realtime. Besides that it does not do much (yet).
+The web interface visualizes the rowing metrics on any device that can run a browser (i.e. a smartphone that you attach to your rowing machine while training). It uses websockets to show the rowing status in Realtime. Besides that it does not do much (yet).

@@ -46,7 +46,7 @@ FTMS supports different types of fitness machines. Open Rowing Monitor currently
I originally started this project, because my rowing machine (Sportstech WRX700) has a very simple computer and I wanted to build something with a clean and simple interface that calculates more realistic metrics. Also, this was a good reason to learn a bit more about Bluetooth and all its specifics.
-The original proof of concept version started as a sketch on an ardunio, but when I started adding things like a web frontend and BLE I moved it to the much more powerful Raspberry Pi. Maybe using a Raspi for this small IoT-project is a bit of an overkill, but it has the capacity for further features such as syncing training data or rowing games. And it has USB-Ports that I can use to charge my phone while rowing :-)
+The original proof of concept version started as a sketch on an Arduino, but when I started adding things like a web frontend and BLE I moved it to the much more powerful Raspberry Pi. Maybe using a Raspberry Pi for this small IoT-project is a bit of an overkill, but it has the capacity for further features such as syncing training data or rowing games. And it has USB-Ports that I can use to charge my phone while rowing :-)
## Further information
diff --git a/app/ble/RowingMachinePeripheral.js b/app/ble/RowingMachinePeripheral.js
index e5eb3d2..5972aa9 100644
--- a/app/ble/RowingMachinePeripheral.js
+++ b/app/ble/RowingMachinePeripheral.js
@@ -50,7 +50,6 @@ function createRowingMachinePeripheral (options) {
bleno.on('accept', (clientAddress) => {
log.debug(`ble central connected: ${clientAddress}`)
- // todo: do we need this?
bleno.updateRssi()
})
diff --git a/app/client/app.js b/app/client/app.js
index 4b9ef3b..ce7edf3 100644
--- a/app/client/app.js
+++ b/app/client/app.js
@@ -8,6 +8,7 @@
// eslint-disable-next-line no-unused-vars
export function createApp () {
const fields = ['strokesTotal', 'distanceTotal', 'caloriesTotal', 'power', 'splitFormatted', 'strokesPerMinute', 'durationTotal']
+ let socket
initWebsocket()
resetFields()
@@ -16,7 +17,7 @@ export function createApp () {
function initWebsocket () {
// use the native websocket implementation of browser to communicate with backend
// eslint-disable-next-line no-undef
- const socket = new WebSocket(`ws://${location.host}`)
+ socket = new WebSocket(`ws://${location.host}`)
socket.addEventListener('open', (event) => {
console.log('websocket openend')
@@ -96,7 +97,7 @@ export function createApp () {
function reset () {
resetFields()
- socket.send(JSON.stringify({ command: 'reset' }))
+ if (socket)socket.send(JSON.stringify({ command: 'reset' }))
}
return {
diff --git a/app/server.js b/app/server.js
index e3c3abd..b5a6588 100644
--- a/app/server.js
+++ b/app/server.js
@@ -22,7 +22,7 @@ import { recordRowingSession, replayRowingSession } from './tools/RowingRecorder
log.setLevel(log.levels.INFO)
const peripheral = createRowingMachinePeripheral({
- simulateIndoorBike: true
+ simulateIndoorBike: false
})
peripheral.on('controlPoint', (event) => {
diff --git a/doc/attribution.md b/doc/attribution.md
index f0ee565..0ec60b8 100644
--- a/doc/attribution.md
+++ b/doc/attribution.md
@@ -1,6 +1,6 @@
# Attribution
-Open Rowing Monitor uses some great work by others. Thank you for all the great ressources that helped me to make this project possible. I especially would like to thank:
+Open Rowing Monitor uses some great work by others. Thank you for all the great resources that helped me to make this project possible. I especially would like to thank:
* A lot of helpful information for building the physics engine of the rowing machine was found in this scientific work by Anu Dudhia: [The Physics of Ergometers](http://eodg.atm.ox.ac.uk/user/dudhia/rowing/physics/ergometer.html).
@@ -8,4 +8,4 @@ Open Rowing Monitor uses some great work by others. Thank you for all the great
* The app icon is based on this [image of a rowing machine](https://thenounproject.com/term/rowing-machine/659265) by [Gan Khoon Lay](https://thenounproject.com/leremy/) licensed under [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/).
-* Bluetooth is quite a complex biest, luckily the Bluetooth SIG releases all the [specifications here](https://www.bluetooth.com/specifications/specs)
+* Bluetooth is quite a complex beast, luckily the Bluetooth SIG releases all the [specifications here](https://www.bluetooth.com/specifications/specs)
diff --git a/doc/backlog.md b/doc/backlog.md
index cfac5fd..4991836 100644
--- a/doc/backlog.md
+++ b/doc/backlog.md
@@ -4,17 +4,21 @@ This is the very minimalistic Backlog for further development of this project.
## Soon
-* check todo markers in code and add them to this backlog
* cleanup of the server.js start file
* figure out where to set the Service Advertising Data (FTMS.pdf p 15)
-* Web UI: replace fullscreen button with exit Button when started from homescreen
+* Web UI: replace fullscreen button with exit Button when started from home screen
* investigate bug: crash, when one unsubscribe to BLE "Generic Attribute", probably a bleno bug "handleAttribute.emit is not a function"
-* set up a raspi with the installation instructions to see if they are correct
+* add photo of wired device to installation instructions
+* what value should we use for split, if we are in a rowing pause? technically should be infinity...
+* set up a Raspberry Pi with the installation instructions to see if they are correct
## Later
+* implement the proprietary Concept2 PM BLE protocol as described here [Concept2 PM Bluetooth Smart Communication Interface](https://www.concept2.co.uk/files/pdf/us/monitors/PM5_BluetoothSmartInterfaceDefinition.pdf)
+* add some attributes to BLE DeviceInformationService
* add a config file
* presets for rowing machine specific config parameters
+* improve the physics model for waterrowers
* validate FTMS with more training applications and harden implementation
* make Web UI a proper Web Application (tooling and SPA framework)
* record the workout and show a visual graph of metrics
@@ -26,3 +30,4 @@ This is the very minimalistic Backlog for further development of this project.
* add video playback in background of Web UI
* implement or integrate some rowing games
* add possibility to define workouts (i.e. training intervals with goals)
+* directly attach a touchscreen to the Raspberry Pi and automatically show WebUI on this in kiosk mode
diff --git a/doc/installation.md b/doc/installation.md
index 4b75f23..b2cee1b 100644
--- a/doc/installation.md
+++ b/doc/installation.md
@@ -7,9 +7,9 @@ This guide roughly explains how to set up your device. I will probably build an
* A Raspberry Pi that supports Bluetooth Low Energy (Pi 3 or Pi 4). Probably this also runs on other devices.
* An SD Card, any size above 4GB should be fine
* A rowing machine (obviously) with some way to measure the rotation of the flywheel
- * the WRX700 has a build in reed sensor that I can directly connect to the GPIO pins of the raspi
+ * the WRX700 has a build in reed sensor that I can directly connect to the GPIO pins of the Raspberry Pi
* if your machine doesn't have a sensor, it should be easy to build something similar (magnetically or optical)
-* Some dupont wires to connect the GPIO pins to the sensor
+* Some Dupont cables to connect the GPIO pins to the sensor
## Software Installation
@@ -79,11 +79,11 @@ WantedBy=multi-user.target
## Hardware Installation
-Basically all thats left to do is hook up your reed sensor to the GPIO pins of the Raspberry Pi.
+Basically all that's left to do is hook up your reed sensor to the GPIO pins of the Raspberry Pi.
todo: add a photo of the wired device
-Open Rowing Monitor reads the sensor signal from GPIO port 17 and expects it to pull on GND if the sensor is closed. To get a stable reading you should add a pull-up resistor to that pin. I prefer to use the internal resitor of the raspi to keep the wiring simple but of course you can also go with an external circuit.
+Open Rowing Monitor reads the sensor signal from GPIO port 17 and expects it to pull on GND if the sensor is closed. To get a stable reading you should add a pull-up resistor to that pin. I prefer to use the internal resistor of the Raspberry Pi to keep the wiring simple but of course you can also go with an external circuit.
The internal pull-up can be enabled as described [here](https://www.raspberrypi.org/documentation/configuration/config-txt/gpio.md). So its as simple as adding the following to `/boot/config.txt` and then rebooting the device.
diff --git a/package-lock.json b/package-lock.json
index 905a886..9ca13fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -441,6 +441,12 @@
"delayed-stream": "~1.0.0"
}
},
+ "commander": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz",
+ "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==",
+ "dev": true
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -515,8 +521,7 @@
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "optional": true
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
},
"deep-is": {
"version": "0.1.3",
@@ -614,6 +619,12 @@
"ansi-colors": "^4.1.1"
}
},
+ "entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+ "dev": true
+ },
"epoll": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/epoll/-/epoll-4.0.0.tgz",
@@ -1220,6 +1231,12 @@
"has-symbols": "^1.0.1"
}
},
+ "get-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true
+ },
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
@@ -1348,6 +1365,12 @@
"sshpk": "^1.7.0"
}
},
+ "husky": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz",
+ "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==",
+ "dev": true
+ },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1411,8 +1434,7 @@
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "optional": true
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"is-arrayish": {
"version": "0.2.1",
@@ -1572,6 +1594,12 @@
"minimist": "^1.2.0"
}
},
+ "jsonc-parser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
+ "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
+ "dev": true
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -1594,6 +1622,15 @@
"type-check": "~0.4.0"
}
},
+ "linkify-it": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
+ "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
+ "dev": true,
+ "requires": {
+ "uc.micro": "^1.0.1"
+ }
+ },
"load-json-file": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
@@ -1627,6 +1664,18 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
},
+ "lodash.differencewith": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz",
+ "integrity": "sha1-uvr7yRi1UVTheRdqALsK76rIVLc=",
+ "dev": true
+ },
+ "lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
+ "dev": true
+ },
"loglevel": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz",
@@ -1649,6 +1698,93 @@
}
}
},
+ "markdown-it": {
+ "version": "12.0.4",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.4.tgz",
+ "integrity": "sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
+ "linkify-it": "^3.0.1",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ }
+ }
+ },
+ "markdownlint": {
+ "version": "0.23.1",
+ "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.23.1.tgz",
+ "integrity": "sha512-iOEwhDfNmq2IJlaA8mzEkHYUi/Hwoa6Ss+HO5jkwUR6wQ4quFr0WzSx+Z9rsWZKUaPbyirIdL1zGmJRkWawr4Q==",
+ "dev": true,
+ "requires": {
+ "markdown-it": "12.0.4"
+ }
+ },
+ "markdownlint-cli": {
+ "version": "0.27.1",
+ "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.27.1.tgz",
+ "integrity": "sha512-p1VV6aSbGrDlpUWzHizAnSNEQAweVR3qUI/AIUubxW7BGPXziSXkIED+uRtSohUlRS/jmqp3Wi4es5j6fIrdeQ==",
+ "dev": true,
+ "requires": {
+ "commander": "~7.1.0",
+ "deep-extend": "~0.6.0",
+ "get-stdin": "~8.0.0",
+ "glob": "~7.1.6",
+ "ignore": "~5.1.8",
+ "js-yaml": "^4.0.0",
+ "jsonc-parser": "~3.0.0",
+ "lodash.differencewith": "~4.5.0",
+ "lodash.flatten": "~4.4.0",
+ "markdownlint": "~0.23.1",
+ "markdownlint-rule-helpers": "~0.14.0",
+ "minimatch": "~3.0.4",
+ "minimist": "~1.2.5",
+ "rc": "~1.2.8"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.1.8",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
+ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
+ "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ }
+ }
+ },
+ "markdownlint-rule-helpers": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.14.0.tgz",
+ "integrity": "sha512-vRTPqSU4JK8vVXmjICHSBhwXUvbfh/VJo+j7hvxqe15tLJyomv3FLgFdFgb8kpj0Fe8SsJa/TZUAXv7/sN+N7A==",
+ "dev": true
+ },
+ "mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+ "dev": true
+ },
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -2209,7 +2345,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "optional": true,
"requires": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
@@ -2604,8 +2739,7 @@
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
- "optional": true
+ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"supports-color": {
"version": "5.5.0",
@@ -2796,6 +2930,12 @@
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
+ "uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+ "dev": true
+ },
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
diff --git a/package.json b/package.json
index 912cee5..61d6e7f 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
"node": ">=12"
},
"scripts": {
- "eslint": "eslint ./app",
+ "prepare": "husky install",
+ "lint": "eslint ./app && markdownlint '**/*.md' --ignore node_modules",
"start": "node app/server.js",
"test": ""
},
@@ -32,6 +33,8 @@
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
- "eslint-plugin-promise": "^4.3.1"
+ "eslint-plugin-promise": "^4.3.1",
+ "husky": "^5.1.3",
+ "markdownlint-cli": "^0.27.1"
}
}