From 34984834727e9b3de84e467af5d5d077e2130140 Mon Sep 17 00:00:00 2001 From: David Maher Date: Mon, 15 Feb 2021 23:36:58 -0500 Subject: [PATCH] Code cleanup --- .eslintrc.js | 1 + .markdownlint.json | 5 - CHANGELOG.md | 291 ----------------------- README.md | 2 +- package-lock.json | 484 ++++++--------------------------------- package.json | 14 +- src/configTypes.ts | 85 +++---- src/ffmpeg.ts | 2 +- src/index.ts | 75 +++--- src/streamingDelegate.ts | 28 +-- 10 files changed, 176 insertions(+), 811 deletions(-) delete mode 100644 .markdownlint.json delete mode 100644 CHANGELOG.md diff --git a/.eslintrc.js b/.eslintrc.js index 5034070a..aeb2ef19 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -20,6 +20,7 @@ module.exports = { '@typescript-eslint/lines-between-class-members': ['error', {"exceptAfterSingleLine": true}], '@typescript-eslint/no-base-to-string': 'error', '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/no-unnecessary-boolean-literal-compare': ['error', {"allowComparingNullableBooleansToTrue": false, "allowComparingNullableBooleansToFalse": false}], '@typescript-eslint/no-var-requires': 'error', '@typescript-eslint/prefer-optional-chain': 'error', diff --git a/.markdownlint.json b/.markdownlint.json deleted file mode 100644 index 52d47b76..00000000 --- a/.markdownlint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "default": true, - "line_length": false, - "no-duplicate-heading": false -} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index eab3cc73..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,291 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. - -## v3.0.4 (2021-02-15) - -### Changes - -- Added warning when attempting to use videoFilter with the copy vcodec. -- Added support for connecting to an MQTT with TLS. -- Updated dependencies. - -## v3.0.3 (2020-09-02) - -### Changes - -- Updated dependencies. - -### Note - -- Homebridge 1.1.3 is now out. It is highly recommended to upgrade as it should completely resolve the issue that caused live video not to work while snapshots continued to update. Once you upgrade, `interfaceName` will no longer have any impact. At some point in the future this plugin will drop support for Homebridge 1.1.2 and lower and also remove the `interfaceName` option. - -## v3.0.2 (2020-08-30) - -### Changes - -- Allow `=` in the URL for HTTP automation for systems that require it. Everything after the `=` will be ignored. - -## v3.0.1 (2020-08-25) - -### Bug Fixes - -- Fixed an issue with inactive camera timeouts that could cause zombie FFmpeg processes. - -## v3.0.0 (2020-08-24) - -### Changes - -- This plugin now includes __experimental__ two-way audio support. Be aware that this feature is likely to be tweaked in the future, and a configuration that works now may need to be altered in the future. -- Better detection of audio and video streams. There should be very few scenarios where `mapvideo` or `mapaudio` are needed anymore, as FFmpeg's stream auto-selection is now set up. -- Default `videoFilter` can be disabled by including `none` in your comma-delimited list of filters. -- Further reorganization of the config UI. - -### Bug Fixes - -- Corrected handling of inactive camera timeouts. You should no longer see timeout messages after cleanly closing a camera stream. -- Fixed `forceMax` not applying to resolution in some scenarios. - -### Breaking Changes - -- `additionalCommandline` has been replaced by `encoderOptions` to better reflect it's intended use. -- `preserveRatio` has been removed and is now active as long as the default `videoFilter` list is active. - -## v2.5.0 (2020-08-23) - -### Changes - -- `forceMax` has been added. This will force the use of `maxWidth`, `maxHeight`, `maxFPS`, and `maxBitrate` when set. -- If `maxWidth`, `maxHeight`, or `maxFPS` are set to `0`, the width, height, or framerate of the source will now be used for the output. -- If `maxBitrate` is set to `0`, the bitrate of the encoder will not be limited. I strongly recommend against this, but it is a better option than setting it to `999999` or similar values, as I've seen in some configs. -- Reorganized config UI options. - -### Bug Fixes - -- Fix handling of IPv6 connections. - -### Breaking Changes - -- Horizontal and vertical flip have been removed. If you need these options, pass `hflip` and/or `vflip` in `videoFilter`. -- `forceMax` has resulted in the removal of `minBitrate`, as it is now redundant. To replicate the old behavior, set `maxBitrate` to the bitrate you want to use and set `forceMax` to true. -- `preserveRatio` is now a boolean to reduce confusion and support the better handling of that option. - -## v2.4.7 (2020-08-17) - -### Changes - -- Changed the way external IP address is determined. This should result in video streams working by default in more setups. - -## v2.4.6 (2020-08-16) - -### Bug Fixes - -- Fix MQTT/HTTP automation when unbridge is used. - -## v2.4.5 (2020-08-15) - -### Changes - -- Return messages and error codes when using HTTP automation. - -### Bug Fixes - -- Fixed bug preventing MQTT/HTTP automation from working. - -## v2.4.4 (2020-08-07) - -### Changes - -- Added support for unbridging specific cameras. This can aid with performance of the camera and Homebridge as a whole, but requires manually adding any unbridged cameras to HomeKit. - -## v2.4.3 (2020-07-29) - -### Changes - -- Trigger switches are now turned on and off with HTTP or MQTT messages as well. -- Removed doorbell stateless switch because it had no functionality. - -## v2.4.2 (2020-07-27) - -### Bug Fixes - -- Properly shut down sessions when devices go inactive. -- Fixed some debug messages. - -## v2.4.1 (2020-07-24) - -### Changes - -- Added warning when multiple NICs detected. - -### Bug Fixes - -- Fix error using copy vcodec. - -## v2.4.0 (2020-07-24) - -### Changes - -- Major rework of code to make future maintenance easier. -- Added setting to limit HTTP server to listening on localhost only. - -## v2.3.2 (2020-07-19) - -### Bug Fixes - -- FFmpeg processes are now killed when the iOS device goes inactive and when stopping Homebridge. - -## v2.3.1 (2020-07-16) - -### Changes - -- Tweaks to logging to reduce confusion and provide more information. -- Added authentication support to MQTT. -- Reduced the FFmpeg log level in debug mode. - -### Bug Fixes - -- The minimum bitrate option is now working again. -- Maximum bitrate and frame rate are no longer capped below what devices request when not set in the config. - -## v2.3.0 (2020-07-14) - -### Changes - -- Added HTTP support for motion detection and doorbells. -- Separated MQTT doorbell and motion messages. - -## v2.2.2 (2020-07-13) - -### Changes - -- Restored ability to specify which network interface to use. - -### Bug Fixes - -- Fixed handling of non-printing characters in config. - -## v2.2.1 (2020-07-11) - -### Bug Fixes - -- Fixed bug preventing Homebridge from starting. - -## v2.2.0 (2020-07-11) - -### Changes - -- Now properly allows for changing camera manufacturer, model, etc. -- Minor tweaks to configuration UI screen. -- Update dependencies. - -### Bug Fixes - -- Fixed a bug when the doorbellSwitch config option was enabled. - -## v2.1.1 (2020-07-08) - -### Changes - -- Update Dependencies. - -## v2.1.0 (2020-07-06) - -### Changes - -- Add MQTT support for Motion Detect (#572), thanks to [fennec622](https://github.com/fennec622). - - See [MQTT Motion Wiki](https://github.com/homebridge-plugins/homebridge-camera-ffmpeg/wiki/MQTT-Motion) for more details. -- Add stateless button for doorbell cameras. -- Add option to disable manual automation switches. -- Re-Added videoFilter. - -### Bug Fixes - -- Fixed most FFmpeg issues where users were receiving issues with ffmpeg exit 1 error. -- Fixed Logging. -- Fixed most videoFilter configs not working. - -## v2.0.1 (2020-06-28) - -### Changes - -- Update Dependencies. - -## v2.0.0 (2020-06-19) - -### Breaking Changes - -- Code has been refactored to typescript, thanks to [Brandawg93](https://github.com/Brandawg93). -- Plugin requires homebridge >= 1.0.0. -- Cameras no longer need to be manually added to homebridge - - Cameras are now bridged instead of being created as external accessories in homebridge. - - Once you update, you will see two copies of each of your cameras. - - You will need to manually remove the old cameras from HomeKit by going into the cameras' settings and choosing "Remove Camera from Home". - - The new bridged cameras will not have this option, and will instead have a "Bridge" button. \* You will also need to copy over any automations that you had tied to your cameras, such as motion detection. - -#### Other Changes - -- Google Drive Upload has been removed in this update. PRs are welcome for other Video Cloud Options. - -## v1.3.0 (2020-06-18) - -### Changes - -- Update ffmpeg-for-homebridge to 0.0.6. - -## v1.2.2 (2020-05-28) - -### Changes - -- Fix for Fake Motion Sensor, it was not reseting after Motion Events. - -## v1.2.1 (2020-05-28) - -### Changes - -- Fixes [#522](https://github.com/homebridge-plugins/homebridge-camera-ffmpeg/issues/522), Cleans Up and Condenses the code around the motion switch. - -## v1.2.0 (2020-05-27) - -### Changes - -- Update ffmpeg-for-homebridge to 0.0.5. - -## v1.1.1 (2020-05-14) - -### Changes - -- Adds debug log for `videoProcessor`. - -## v1.1.0 (2020-05-13) - -### Features - -- Adds an option to have a camera behave like a video doorbell, including a switch to trigger doorbell events (automate the switch to get notifications) -- Add Manufacturer, Model, Serial, and Firmware Revision into config.schema.json. - -## v1.0.0 (2020-05-11) - -### Breaking Changes - -homebridge-camera-ffmpeg now comes bundled with it's own pre-built static ffmpeg binaries that are compiled with support for audio (libfdk-aac) and hardware decoding (h264_omx). The following platforms are supported: - -- Raspbian Linux - armv6l (armv7l) -- Debian/Ubuntu Linux - x86_64, armv7l, aarch64 -- Alpine Linux - x86_64, armv6l, aarch64 -- macOS (10.14+) - x86_64 -- Windows 10 - x86_64 - -If your platform is not supported the plugin will fallback to using your global install of `ffmpeg` automatically. - -Should you wish to force the plugin to use the global install of `ffmpeg` instead of the provided copy, you can simply set `videoProcessor` option to `ffmpeg`. Example: - -```json -{ - "platform": "Camera-ffmpeg", - "videoProcessor": "ffmpeg", - "cameras": [ - ... - ] -} -``` diff --git a/README.md b/README.md index e193dfc0..58ff7886 100755 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ Other users have been sharing configurations that work for them on our GitHub si - `mqtt`: Defines the hostname or IP of the MQTT broker to connect to for MQTT-based automation. If not set, MQTT support is not started. See the project site for [more information on using MQTT](https://sunoo.github.io/homebridge-camera-ffmpeg/automation/mqtt.html). - `portmqtt`: The port of the MQTT broker. (Default: `1883`) -- `tlsmqtt`: Use TLS to connect to the MQTT broker. +- `tlsmqtt`: Use TLS to connect to the MQTT broker. (Default: `false`) - `usermqtt`: The username used to connect to your MQTT broker. If not set, no authentication is used. - `passmqtt`: The password used to connect to your MQTT broker. If not set, no authentication is used. - `topic`: The base MQTT topic to subscribe to. (Default: `homebridge`) diff --git a/package-lock.json b/package-lock.json index b19d86ef..f45b130f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "homebridge-camera-ffmpeg", - "version": "3.0.4", + "version": "3.0.5", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "3.0.4", + "version": "3.0.5", "funding": [ { "type": "kofi", @@ -33,11 +33,10 @@ }, "devDependencies": { "@types/node": "^14.14.28", - "@typescript-eslint/eslint-plugin": "^4.15.0", - "@typescript-eslint/parser": "^4.15.0", - "eslint": "7.20.0", + "@typescript-eslint/eslint-plugin": "^4.15.1", + "@typescript-eslint/parser": "^4.15.1", + "eslint": "^7.20.0", "homebridge": "^1.1.7", - "markdownlint-cli": "^0.26.0", "rimraf": "^3.0.2", "typescript": "^4.1.5" }, @@ -203,13 +202,13 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.0.tgz", - "integrity": "sha512-DJgdGZW+8CFUTz5C/dnn4ONcUm2h2T0itWD85Ob5/V27Ndie8hUoX5HKyGssvR8sUMkAIlUc/AMK67Lqa3kBIQ==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz", + "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "4.15.0", - "@typescript-eslint/scope-manager": "4.15.0", + "@typescript-eslint/experimental-utils": "4.15.1", + "@typescript-eslint/scope-manager": "4.15.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -235,15 +234,15 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.0.tgz", - "integrity": "sha512-V4vaDWvxA2zgesg4KPgEGiomWEBpJXvY4ZX34Y3qxK8LUm5I87L+qGIOTd9tHZOARXNRt9pLbblSKiYBlGMawg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz", + "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.0", - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/typescript-estree": "4.15.0", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, @@ -259,14 +258,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.0.tgz", - "integrity": "sha512-L6Dtbq8Bc7g2aZwnIBETpmUa9XDKCMzKVwAArnGp5Mn7PRNFjf3mUzq8UeBjL3K8t311hvevnyqXAMSmxO8Gpg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", + "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "4.15.0", - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/typescript-estree": "4.15.0", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", "debug": "^4.1.1" }, "engines": { @@ -286,13 +285,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.0.tgz", - "integrity": "sha512-CSNBZnCC2jEA/a+pR9Ljh8Y+5TY5qgbPz7ICEk9WCpSEgT6Pi7H2RIjxfrrbUXvotd6ta+i27sssKEH8Azm75g==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/visitor-keys": "4.15.0" + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -303,9 +302,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.0.tgz", - "integrity": "sha512-su4RHkJhS+iFwyqyXHcS8EGPlUVoC+XREfy5daivjLur9JP8GhvTmDipuRpcujtGC4M+GYhUOJCPDE3rC5NJrg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -316,13 +315,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.0.tgz", - "integrity": "sha512-jG6xTmcNbi6xzZq0SdWh7wQ9cMb2pqXaUp6bUZOMsIlu5aOlxGxgE/t6L/gPybybQGvdguajXGkZKSndZJpksA==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/visitor-keys": "4.15.0", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -343,12 +342,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.0.tgz", - "integrity": "sha512-RnDtJwOwFucWFAMjG3ghCG/ikImFJFEg20DI7mn4pHEx3vC48lIAoyjhffvfHmErRDboUPC7p9Z2il4CLb7qxA==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.15.0", + "@typescript-eslint/types": "4.15.1", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -799,15 +798,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -951,12 +941,6 @@ "node": ">=8.6" } }, - "node_modules/entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, "node_modules/es-abstract": { "version": "1.18.0-next.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", @@ -1408,18 +1392,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1717,12 +1689,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, "node_modules/ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -2044,12 +2010,6 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, - "node_modules/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 - }, "node_modules/leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", @@ -2071,33 +2031,12 @@ "node": ">= 0.8.0" } }, - "node_modules/linkify-it": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz", - "integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==", - "dev": true, - "dependencies": { - "uc.micro": "^1.0.1" - } - }, "node_modules/lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, - "node_modules/lodash.differencewith": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz", - "integrity": "sha1-uvr7yRi1UVTheRdqALsK76rIVLc=", - "dev": true - }, - "node_modules/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 - }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2110,98 +2049,6 @@ "node": ">=10" } }, - "node_modules/markdown-it": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.2.tgz", - "integrity": "sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1", - "entities": "~2.0.0", - "linkify-it": "^3.0.1", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - }, - "bin": { - "markdown-it": "bin/markdown-it.js" - } - }, - "node_modules/markdown-it/node_modules/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 - }, - "node_modules/markdownlint": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.22.0.tgz", - "integrity": "sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w==", - "dev": true, - "dependencies": { - "markdown-it": "12.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/markdownlint-cli": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.26.0.tgz", - "integrity": "sha512-biLfeGNZG9nw0yJbtFBzRlew2/P5w7JSseKwolSox3zejs7dLpGvPgqbC+iqJnqqGWcWLtXaXh8bBEKWmfl10A==", - "dev": true, - "dependencies": { - "commander": "~6.2.1", - "deep-extend": "~0.6.0", - "get-stdin": "~8.0.0", - "glob": "~7.1.6", - "ignore": "~5.1.8", - "js-yaml": "~3.14.1", - "jsonc-parser": "~3.0.0", - "lodash.differencewith": "~4.5.0", - "lodash.flatten": "~4.4.0", - "markdownlint": "~0.22.0", - "markdownlint-rule-helpers": "~0.13.0", - "minimatch": "~3.0.4", - "minimist": "~1.2.5", - "rc": "~1.2.8" - }, - "bin": { - "markdownlint": "markdownlint.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/markdownlint-cli/node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/markdownlint-cli/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/markdownlint-rule-helpers": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.13.0.tgz", - "integrity": "sha512-rRY0itbcHG4e+ntz0bbY3AIceSJMKS0TafEMgEtKVHRZ54/JUSy6/4ypCL618RlJvYRej+xMLxX5nkJqIeTZaQ==", - "dev": true - }, - "node_modules/mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -2646,30 +2493,6 @@ } ] }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/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=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -3262,12 +3085,6 @@ "node": ">=4.2.0" } }, - "node_modules/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 - }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -3556,13 +3373,13 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.0.tgz", - "integrity": "sha512-DJgdGZW+8CFUTz5C/dnn4ONcUm2h2T0itWD85Ob5/V27Ndie8hUoX5HKyGssvR8sUMkAIlUc/AMK67Lqa3kBIQ==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz", + "integrity": "sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.15.0", - "@typescript-eslint/scope-manager": "4.15.0", + "@typescript-eslint/experimental-utils": "4.15.1", + "@typescript-eslint/scope-manager": "4.15.1", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -3572,55 +3389,55 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.0.tgz", - "integrity": "sha512-V4vaDWvxA2zgesg4KPgEGiomWEBpJXvY4ZX34Y3qxK8LUm5I87L+qGIOTd9tHZOARXNRt9pLbblSKiYBlGMawg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz", + "integrity": "sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.15.0", - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/typescript-estree": "4.15.0", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.0.tgz", - "integrity": "sha512-L6Dtbq8Bc7g2aZwnIBETpmUa9XDKCMzKVwAArnGp5Mn7PRNFjf3mUzq8UeBjL3K8t311hvevnyqXAMSmxO8Gpg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.15.1.tgz", + "integrity": "sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.15.0", - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/typescript-estree": "4.15.0", + "@typescript-eslint/scope-manager": "4.15.1", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/typescript-estree": "4.15.1", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.0.tgz", - "integrity": "sha512-CSNBZnCC2jEA/a+pR9Ljh8Y+5TY5qgbPz7ICEk9WCpSEgT6Pi7H2RIjxfrrbUXvotd6ta+i27sssKEH8Azm75g==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz", + "integrity": "sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/visitor-keys": "4.15.0" + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1" } }, "@typescript-eslint/types": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.0.tgz", - "integrity": "sha512-su4RHkJhS+iFwyqyXHcS8EGPlUVoC+XREfy5daivjLur9JP8GhvTmDipuRpcujtGC4M+GYhUOJCPDE3rC5NJrg==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.15.1.tgz", + "integrity": "sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.0.tgz", - "integrity": "sha512-jG6xTmcNbi6xzZq0SdWh7wQ9cMb2pqXaUp6bUZOMsIlu5aOlxGxgE/t6L/gPybybQGvdguajXGkZKSndZJpksA==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz", + "integrity": "sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.0", - "@typescript-eslint/visitor-keys": "4.15.0", + "@typescript-eslint/types": "4.15.1", + "@typescript-eslint/visitor-keys": "4.15.1", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -3629,12 +3446,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.0.tgz", - "integrity": "sha512-RnDtJwOwFucWFAMjG3ghCG/ikImFJFEg20DI7mn4pHEx3vC48lIAoyjhffvfHmErRDboUPC7p9Z2il4CLb7qxA==", + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz", + "integrity": "sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww==", "dev": true, "requires": { - "@typescript-eslint/types": "4.15.0", + "@typescript-eslint/types": "4.15.1", "eslint-visitor-keys": "^2.0.0" } }, @@ -3972,12 +3789,6 @@ "which-typed-array": "^1.1.2" } }, - "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==", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -4099,12 +3910,6 @@ "ansi-colors": "^4.1.1" } }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, "es-abstract": { "version": "1.18.0-next.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", @@ -4460,12 +4265,6 @@ "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" }, - "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 - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -4690,12 +4489,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -4912,12 +4705,6 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, - "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 - }, "leven": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", @@ -4933,33 +4720,12 @@ "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" - } - }, "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", "dev": true }, - "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 - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4969,84 +4735,6 @@ "yallist": "^4.0.0" } }, - "markdown-it": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.2.tgz", - "integrity": "sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA==", - "dev": true, - "requires": { - "argparse": "^2.0.1", - "entities": "~2.0.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.22.0", - "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.22.0.tgz", - "integrity": "sha512-J4B+iMc12pOdp/wfYi03W2qfAfEyiZzq3qvQh/8vOMNU8vXYY6Jg440EY7dWTBCqROhb1i4nAn3BTByJ5kdx1w==", - "dev": true, - "requires": { - "markdown-it": "12.0.2" - } - }, - "markdownlint-cli": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.26.0.tgz", - "integrity": "sha512-biLfeGNZG9nw0yJbtFBzRlew2/P5w7JSseKwolSox3zejs7dLpGvPgqbC+iqJnqqGWcWLtXaXh8bBEKWmfl10A==", - "dev": true, - "requires": { - "commander": "~6.2.1", - "deep-extend": "~0.6.0", - "get-stdin": "~8.0.0", - "glob": "~7.1.6", - "ignore": "~5.1.8", - "js-yaml": "~3.14.1", - "jsonc-parser": "~3.0.0", - "lodash.differencewith": "~4.5.0", - "lodash.flatten": "~4.4.0", - "markdownlint": "~0.22.0", - "markdownlint-rule-helpers": "~0.13.0", - "minimatch": "~3.0.4", - "minimist": "~1.2.5", - "rc": "~1.2.8" - }, - "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "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 - } - } - }, - "markdownlint-rule-helpers": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.13.0.tgz", - "integrity": "sha512-rRY0itbcHG4e+ntz0bbY3AIceSJMKS0TafEMgEtKVHRZ54/JUSy6/4ypCL618RlJvYRej+xMLxX5nkJqIeTZaQ==", - "dev": true - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5387,26 +5075,6 @@ "integrity": "sha512-dB15eXv3p2jDlbOiNLyMabYg1/sXvppd8DP2J3EOCQ0AkuSXCW2tP7mnVouVLJKgUMY6yP0kcQDVpLCN13h4Xg==", "dev": true }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "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=", - "dev": true - } - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -5828,12 +5496,6 @@ "integrity": "sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==", "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 - }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", diff --git a/package.json b/package.json index bd4b9499..62b7e9d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Homebridge Camera FFmpeg", "name": "homebridge-camera-ffmpeg", - "version": "3.0.4", + "version": "3.0.5", "description": "Homebridge Plugin Providing FFmpeg-based Camera Support", "main": "dist/index.js", "license": "ISC", @@ -24,9 +24,8 @@ } ], "scripts": { - "clean": "rimraf ./dist ./coverage", - "build": "rimraf ./dist ./coverage && tsc", - "format": "markdownlint --fix *.md", + "clean": "rimraf ./dist", + "build": "rimraf ./dist && tsc", "lint": "eslint src/*.ts --fix", "lint-check": "eslint src/*.ts", "prepare": "npm run build", @@ -61,11 +60,10 @@ ], "devDependencies": { "@types/node": "^14.14.28", - "@typescript-eslint/eslint-plugin": "^4.15.0", - "@typescript-eslint/parser": "^4.15.0", - "eslint": "7.20.0", + "@typescript-eslint/eslint-plugin": "^4.15.1", + "@typescript-eslint/parser": "^4.15.1", + "eslint": "^7.20.0", "homebridge": "^1.1.7", - "markdownlint-cli": "^0.26.0", "rimraf": "^3.0.2", "typescript": "^4.1.5" }, diff --git a/src/configTypes.ts b/src/configTypes.ts index 4fffb3f1..a036c5b2 100644 --- a/src/configTypes.ts +++ b/src/configTypes.ts @@ -1,49 +1,52 @@ +import { PlatformIdentifier, PlatformName } from 'homebridge'; + export type FfmpegPlatformConfig = { - name: string; - videoProcessor: string; - interfaceName: string; - mqtt: string; - portmqtt: number; - tlsmqtt: boolean; - usermqtt: string; - passmqtt: string; - topic: string; - porthttp: number; - localhttp: boolean; - cameras: Array; + platform: PlatformName | PlatformIdentifier; + name?: string; + videoProcessor?: string; + interfaceName?: string; + mqtt?: string; + portmqtt?: number; + tlsmqtt?: boolean; + usermqtt?: string; + passmqtt?: string; + topic?: string; + porthttp?: number; + localhttp?: boolean; + cameras?: Array; }; export type CameraConfig = { - name: string; - manufacturer: string; - model: string; - serialNumber: string; - firmwareRevision: string; - motion: boolean; - doorbell: boolean; - switches: boolean; - motionTimeout: number; - unbridge: boolean; - videoConfig: VideoConfig; + name?: string; + manufacturer?: string; + model?: string; + serialNumber?: string; + firmwareRevision?: string; + motion?: boolean; + doorbell?: boolean; + switches?: boolean; + motionTimeout?: number; + unbridge?: boolean; + videoConfig?: VideoConfig; }; export type VideoConfig = { - source: string; - stillImageSource: string; - returnAudioTarget: string; - maxStreams: number; - maxWidth: number; - maxHeight: number; - maxFPS: number; - maxBitrate: number; - forceMax: boolean; - vcodec: string; - packetSize: number; - videoFilter: string; - encoderOptions: string; - mapvideo: string; - mapaudio: string; - audio: boolean; - debug: boolean; - debugReturn: boolean; + source?: string; + stillImageSource?: string; + returnAudioTarget?: string; + maxStreams?: number; + maxWidth?: number; + maxHeight?: number; + maxFPS?: number; + maxBitrate?: number; + forceMax?: boolean; + vcodec?: string; + packetSize?: number; + videoFilter?: string; + encoderOptions?: string; + mapvideo?: string; + mapaudio?: string; + audio?: boolean; + debug?: boolean; + debugReturn?: boolean; }; \ No newline at end of file diff --git a/src/ffmpeg.ts b/src/ffmpeg.ts index b0539ef7..083a1e79 100644 --- a/src/ffmpeg.ts +++ b/src/ffmpeg.ts @@ -8,7 +8,7 @@ export class FfmpegProcess { private readonly process: ChildProcess; constructor(cameraName: string, sessionId: string, videoProcessor: string, ffmpegArgs: string, log: Logger, - debug: boolean, delegate: StreamingDelegate, callback?: StreamRequestCallback) { + debug = false, delegate: StreamingDelegate, callback?: StreamRequestCallback) { log.debug('Stream command: ' + videoProcessor + ' ' + ffmpegArgs, cameraName, debug); let started = false; diff --git a/src/index.ts b/src/index.ts index 82c1e6c8..182f0797 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,51 +43,49 @@ class FfmpegPlatform implements DynamicPlatformPlugin { constructor(log: Logging, config: PlatformConfig, api: API) { this.log = new Logger(log); this.api = api; - this.config = config as unknown as FfmpegPlatformConfig; + this.config = config as FfmpegPlatformConfig; - if (this.config.cameras) { - this.config.cameras.forEach((cameraConfig: CameraConfig) => { - let error = false; + this.config.cameras?.forEach((cameraConfig: CameraConfig) => { + let error = false; - if (!cameraConfig.name) { - this.log.error('One of your cameras has no name configured. This camera will be skipped.'); - error = true; - } - if (!cameraConfig.videoConfig) { - this.log.error('The videoConfig section is missing from the config. This camera will be skipped.', cameraConfig.name); + if (!cameraConfig.name) { + this.log.error('One of your cameras has no name configured. This camera will be skipped.'); + error = true; + } + if (!cameraConfig.videoConfig) { + this.log.error('The videoConfig section is missing from the config. This camera will be skipped.', cameraConfig.name); + error = true; + } else { + if (!cameraConfig.videoConfig.source) { + this.log.error('There is no source configured for this camera. This camera will be skipped.', cameraConfig.name); error = true; } else { - if (!cameraConfig.videoConfig.source) { - this.log.error('There is no source configured for this camera. This camera will be skipped.', cameraConfig.name); - error = true; - } else { - const sourceArgs = cameraConfig.videoConfig.source.split(/\s+/); - if (!sourceArgs.includes('-i')) { - this.log.warn('The source for this camera is missing "-i", it is likely misconfigured.', cameraConfig.name); - } - } - if (cameraConfig.videoConfig.stillImageSource) { - const stillArgs = cameraConfig.videoConfig.stillImageSource.split(/\s+/); - if (!stillArgs.includes('-i')) { - this.log.warn('The stillImageSource for this camera is missing "-i", it is likely misconfigured.', cameraConfig.name); - } + const sourceArgs = cameraConfig.videoConfig.source.split(/\s+/); + if (!sourceArgs.includes('-i')) { + this.log.warn('The source for this camera is missing "-i", it is likely misconfigured.', cameraConfig.name); } - if (cameraConfig.videoConfig.vcodec === 'copy' && !!cameraConfig.videoConfig.videoFilter) { - this.log.warn('A videoFilter is defined, but the copy vcodec is being used. This will be ignored.', cameraConfig.name); + } + if (cameraConfig.videoConfig.stillImageSource) { + const stillArgs = cameraConfig.videoConfig.stillImageSource.split(/\s+/); + if (!stillArgs.includes('-i')) { + this.log.warn('The stillImageSource for this camera is missing "-i", it is likely misconfigured.', cameraConfig.name); } } + if (cameraConfig.videoConfig.vcodec === 'copy' && cameraConfig.videoConfig.videoFilter) { + this.log.warn('A videoFilter is defined, but the copy vcodec is being used. This will be ignored.', cameraConfig.name); + } + } - if (!error) { - const uuid = hap.uuid.generate(cameraConfig.name); - if (this.cameraConfigs.has(uuid)) { - // Camera names must be unique - this.log.warn('Multiple cameras are configured with this name. Duplicate cameras will be skipped.', cameraConfig.name); - } else { - this.cameraConfigs.set(uuid, cameraConfig); - } + if (!error) { + const uuid = hap.uuid.generate(cameraConfig.name!); + if (this.cameraConfigs.has(uuid)) { + // Camera names must be unique + this.log.warn('Multiple cameras are configured with this name. Duplicate cameras will be skipped.', cameraConfig.name); + } else { + this.cameraConfigs.set(uuid, cameraConfig); } - }); - } + } + }); api.on(APIEvent.DID_FINISH_LAUNCHING, this.didFinishLaunching.bind(this)); } @@ -306,7 +304,6 @@ class FfmpegPlatform implements DynamicPlatformPlugin { mqtttopic = this.config.topic; } this.log.info('Setting up MQTT connection with topic ' + mqtttopic + '...'); - this.log.debug((this.config.tlsmqtt ? 'mqtts://' : 'mqtt://') + this.config.mqtt + ':' + portmqtt); const client = mqtt.connect((this.config.tlsmqtt ? 'mqtts://' : 'mqtt://') + this.config.mqtt + ':' + portmqtt, { 'username': this.config.usermqtt, 'password': this.config.passmqtt @@ -349,7 +346,7 @@ class FfmpegPlatform implements DynamicPlatformPlugin { for (const [uuid, cameraConfig] of this.cameraConfigs) { if (cameraConfig.unbridge) { - const accessory = new Accessory(cameraConfig.name, uuid); + const accessory = new Accessory(cameraConfig.name!, uuid); this.log.info('Configuring unbridged accessory...', accessory.displayName); this.setupAccessory(accessory, cameraConfig); this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]); @@ -357,7 +354,7 @@ class FfmpegPlatform implements DynamicPlatformPlugin { } else { const cachedAccessory = this.cachedAccessories.find((curAcc: PlatformAccessory) => curAcc.UUID === uuid); if (!cachedAccessory) { - const accessory = new Accessory(cameraConfig.name, uuid); + const accessory = new Accessory(cameraConfig.name!, uuid); this.log.info('Configuring bridged accessory...', accessory.displayName); this.setupAccessory(accessory, cameraConfig); this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); diff --git a/src/streamingDelegate.ts b/src/streamingDelegate.ts index 444f9955..70dae48e 100644 --- a/src/streamingDelegate.ts +++ b/src/streamingDelegate.ts @@ -74,12 +74,12 @@ export class StreamingDelegate implements CameraStreamingDelegate { ongoingSessions: Record = {}; timeouts: Record = {}; - constructor(log: Logger, cameraConfig: CameraConfig, api: API, hap: HAP, videoProcessor: string, interfaceName?: string) { // eslint-disable-line @typescript-eslint/explicit-module-boundary-types + constructor(log: Logger, cameraConfig: CameraConfig, api: API, hap: HAP, videoProcessor?: string, interfaceName?: string) { // eslint-disable-line @typescript-eslint/explicit-module-boundary-types this.log = log; - this.videoConfig = cameraConfig.videoConfig; + this.videoConfig = cameraConfig.videoConfig!; this.hap = hap; - this.cameraName = cameraConfig.name; + this.cameraName = cameraConfig.name!; this.videoProcessor = videoProcessor || ffmpegPath || 'ffmpeg'; this.interfaceName = interfaceName; @@ -90,7 +90,7 @@ export class StreamingDelegate implements CameraStreamingDelegate { }); const options: CameraControllerOptions = { - cameraStreamCount: cameraConfig.videoConfig.maxStreams || 2, // HomeKit requires at least 2 streams, but 1 is also just fine + cameraStreamCount: this.videoConfig.maxStreams || 2, // HomeKit requires at least 2 streams, but 1 is also just fine delegate: this, streamingOptions: { supportedCryptoSuites: [hap.SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80], @@ -132,12 +132,12 @@ export class StreamingDelegate implements CameraStreamingDelegate { let width = request.width; let height = request.height; if (!isSnapshot) { - if ((this.videoConfig.forceMax && this.videoConfig.maxWidth) || - (request.width > this.videoConfig.maxWidth)) { + if (this.videoConfig.maxWidth !== undefined && + (this.videoConfig.forceMax || request.width > this.videoConfig.maxWidth)) { width = this.videoConfig.maxWidth; } - if ((this.videoConfig.forceMax && this.videoConfig.maxHeight) || - (request.height > this.videoConfig.maxHeight)) { + if (this.videoConfig.maxHeight !== undefined && + (this.videoConfig.forceMax || request.height > this.videoConfig.maxHeight)) { height = this.videoConfig.maxHeight; } } @@ -170,7 +170,7 @@ export class StreamingDelegate implements CameraStreamingDelegate { this.log.debug('Sending snapshot: ' + (resolution.width > 0 ? resolution.width : 'native') + ' x ' + (resolution.height > 0 ? resolution.height : 'native'), this.cameraName, this.videoConfig.debug); - let ffmpegArgs = this.videoConfig.stillImageSource || this.videoConfig.source; + let ffmpegArgs = this.videoConfig.stillImageSource || this.videoConfig.source!; ffmpegArgs += // Still ' -frames:v 1' + @@ -287,11 +287,11 @@ export class StreamingDelegate implements CameraStreamingDelegate { const resolution = this.determineResolution(request.video, false); - let fps = (this.videoConfig.forceMax && this.videoConfig.maxFPS) || - (request.video.fps > this.videoConfig.maxFPS) ? + let fps = (this.videoConfig.maxFPS !== undefined && + (this.videoConfig.forceMax || request.video.fps > this.videoConfig.maxFPS)) ? this.videoConfig.maxFPS : request.video.fps; - let videoBitrate = (this.videoConfig.forceMax && this.videoConfig.maxBitrate) || - (request.video.max_bit_rate > this.videoConfig.maxBitrate) ? + let videoBitrate = (this.videoConfig.maxBitrate !== undefined && + (this.videoConfig.forceMax || request.video.max_bit_rate > this.videoConfig.maxBitrate)) ? this.videoConfig.maxBitrate : request.video.max_bit_rate; if (vcodec === 'copy') { @@ -308,7 +308,7 @@ export class StreamingDelegate implements CameraStreamingDelegate { (resolution.height > 0 ? resolution.height : 'native') + ', ' + (fps > 0 ? fps : 'native') + ' fps, ' + (videoBitrate > 0 ? videoBitrate : '???') + ' kbps', this.cameraName); - let ffmpegArgs = this.videoConfig.source; + let ffmpegArgs = this.videoConfig.source!; ffmpegArgs += // Video (this.videoConfig.mapvideo ? ' -map ' + this.videoConfig.mapvideo : ' -an -sn -dn') +