diff --git a/package-lock.json b/package-lock.json index d2f8a6f..b04a61d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -250,6 +250,19 @@ } } }, + "@hijef/pushbullet": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@hijef/pushbullet/-/pushbullet-2.4.2.tgz", + "integrity": "sha512-Mbcfb6wQhdPEHbCb1pVZGWmn3QVcOKeIvpYRIbJsIA0ULA4/v6XNUYVlzdn/OEgUlmqJhGgn+4CGqNzjvODj9w==", + "requires": { + "clone": "^2.1.2", + "mime": "^2.4.6", + "node-forge": "^0.10.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "ws": "^7.3.1" + } + }, "@mrmlnc/readdir-enhanced": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", @@ -738,6 +751,193 @@ "eslint-visitor-keys": "^1.1.0" } }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -772,6 +972,18 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, "ansi-align": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", @@ -829,6 +1041,12 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -997,10 +1215,12 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": true }, "asynckit": { "version": "0.4.0", @@ -1133,12 +1353,28 @@ "tweetnacl": "^0.14.3" } }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bl": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", @@ -1149,6 +1385,12 @@ "readable-stream": "^3.4.0" } }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, "bn.js": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", @@ -1419,6 +1661,40 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1604,6 +1880,15 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -1757,6 +2042,12 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -1780,6 +2071,50 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -1818,6 +2153,31 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -1949,6 +2309,12 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -2258,6 +2624,50 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -2304,6 +2714,12 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, "enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", @@ -2357,6 +2773,15 @@ "integrity": "sha512-suh+Vm00GnPQgXpmONTkcUT9LgBSL6sJrRnJxbykT0j+ONjzmIS+1U3ne467ArdZN/42/npp+GnhtwkLQ+vUjw==", "dev": true }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3381,6 +3806,12 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -3390,6 +3821,13 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -3481,6 +3919,48 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -3531,6 +4011,48 @@ "map-cache": "^0.2.2" } }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3548,6 +4070,50 @@ "universalify": "^1.0.0" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3975,6 +4541,12 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -4029,6 +4601,12 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -4450,6 +5028,12 @@ "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", "dev": true }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -4645,6 +5229,34 @@ } } }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -4801,6 +5413,15 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -5145,6 +5766,24 @@ } } }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -5196,6 +5835,31 @@ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5207,6 +5871,13 @@ "integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==", "dev": true }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -5232,6 +5903,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, "no-case": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", @@ -5247,9 +5924,9 @@ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-forge": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", - "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" }, "node-libs-browser": { "version": "2.2.1", @@ -5732,6 +6409,49 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5958,6 +6678,12 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, "proto-props": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/proto-props/-/proto-props-2.0.0.tgz", @@ -5969,6 +6695,12 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -6011,6 +6743,29 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -6184,29 +6939,6 @@ } } }, - "pushbullet": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pushbullet/-/pushbullet-2.4.0.tgz", - "integrity": "sha512-9CkgzAmBOv/ekxI4oqlFXdFIdKEMQgv1NBUbQYYxo/OsGYdnM2D9xEtWLQLkMAkpZUwbNr9lHq7a27082+eQMw==", - "requires": { - "clone": "^2.1.2", - "mime": "^2.4.0", - "node-forge": "^0.7.6", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "ws": "^6.1.2" - }, - "dependencies": { - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, "pushover-notifications": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/pushover-notifications/-/pushover-notifications-1.2.2.tgz", @@ -6452,6 +7184,13 @@ "rc": "^1.2.8" } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true, + "optional": true + }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -6610,6 +7349,15 @@ "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz", "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=" }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -6629,6 +7377,17 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, "scmp": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", @@ -6668,6 +7427,15 @@ "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", "dev": true }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -6909,6 +7677,12 @@ } } }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -7015,6 +7789,15 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", @@ -7088,6 +7871,16 @@ } } }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, "stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", @@ -7133,6 +7926,12 @@ } } }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -7295,6 +8094,132 @@ "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", "dev": true }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -7311,6 +8236,48 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "timers-browserify": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", @@ -7576,6 +8543,12 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.15.1.tgz", "integrity": "sha512-n+UXrN8i5ioo7kqT/nF8xsEzLaqFra7k32SEsSPwvXVGyAcRgV/FUQN/sgfptJTR1oRmmq7z4IXMFSM7im7C9A==" }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -7638,6 +8611,24 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -7693,6 +8684,13 @@ } } }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, "update-notifier": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", @@ -7888,11 +8886,354 @@ "loose-envify": "^1.0.0" } }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "optional": true, + "requires": { + "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" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "weak-map": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=" }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8001,6 +9342,15 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8123,6 +9473,18 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "yaml": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", diff --git a/package.json b/package.json index 72c06a8..57f2ab1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "homepage": "https://github.com/jef/nvidia-snatcher#readme", "dependencies": { + "@hijef/pushbullet": "^2.4.2", "@slack/web-api": "^5.12.0", "chalk": "^4.1.0", "cheerio": "^1.0.0-rc.3", @@ -38,7 +39,6 @@ "puppeteer-extra-plugin-adblocker": "^2.11.6", "puppeteer-extra-plugin-block-resources": "^2.2.7", "puppeteer-extra-plugin-stealth": "^2.6.2", - "pushbullet": "^2.4.0", "pushover-notifications": "^1.2.2", "twilio": "^3.49.4", "twitter": "^1.7.1", @@ -57,6 +57,7 @@ "rimraf": "^3.0.2", "ts-node": "^9.0.0", "typescript": "^4.0.2", + "webpack": "^4.44.2", "xo": "^0.33.1" }, "xo": { diff --git a/src/config.ts b/src/config.ts index d5d0d7d..acec47a 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,10 +1,10 @@ import {banner} from './banner'; console.log(banner); -import {config} from 'dotenv'; +import {config as config_} from 'dotenv'; import path from 'path'; -config({path: path.resolve(__dirname, '../.env')}); +config_({path: path.resolve(__dirname, '../.env')}); /** * Returns environment variable, given array, or default array. @@ -91,7 +91,7 @@ const notifications = { number: envOrString(process.env.PHONE_NUMBER) }, playSound: envOrString(process.env.PLAY_SOUND), - pushBulletApiKey: envOrString(process.env.PUSHBULLET), + pushbullet: envOrString(process.env.PUSHBULLET), pushover: { priority: envOrString(process.env.PUSHOVER_PRIORITY), token: envOrString(process.env.PUSHOVER_TOKEN), @@ -128,8 +128,8 @@ const nvidia = { const page = { height: 1080, inStockWaitTime: envOrNumber(process.env.IN_STOCK_WAIT_TIME), - navigationTimeout: envOrNumber(process.env.PAGE_TIMEOUT, 30000), screenshot: envOrBoolean(process.env.SCREENSHOT), + timeout: envOrNumber(process.env.PAGE_TIMEOUT, 30000), userAgent: envOrString(process.env.USER_AGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'), width: 1920 }; @@ -149,7 +149,7 @@ const store = { stores: envOrArray(process.env.STORES, ['nvidia']) }; -export const Config = { +export const config = { browser, logLevel, notifications, diff --git a/src/index.ts b/src/index.ts index 4336f76..5b166a0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,16 +1,16 @@ -import {Config} from './config'; -import {Logger} from './logger'; import {Stores} from './store/model'; import {adBlocker} from './adblocker'; +import {config} from './config'; import {fetchLinks} from './store/fetch-links'; import {getSleepTime} from './util'; +import {logger} from './logger'; import puppeteer from 'puppeteer-extra'; import resourceBlock from 'puppeteer-extra-plugin-block-resources'; import stealthPlugin from 'puppeteer-extra-plugin-stealth'; import {tryLookupAndLoop} from './store'; puppeteer.use(stealthPlugin()); -if (Config.browser.lowBandwidth) { +if (config.browser.lowBandwidth) { puppeteer.use(resourceBlock({ blockedTypes: new Set(['image', 'font']) })); @@ -23,7 +23,7 @@ if (Config.browser.lowBandwidth) { */ async function main() { if (Stores.length === 0) { - Logger.error('✖ no stores selected', Stores); + logger.error('✖ no stores selected', Stores); return; } @@ -31,28 +31,28 @@ async function main() { // Skip Chromium Linux Sandbox // https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#setting-up-chrome-linux-sandbox - if (Config.browser.isTrusted) { + if (config.browser.isTrusted) { args.push('--no-sandbox'); args.push('--disable-setuid-sandbox'); } // Add the address of the proxy server if defined - if (Config.proxy.address) { - args.push(`--proxy-server=http://${Config.proxy.address}:${Config.proxy.port}`); + if (config.proxy.address) { + args.push(`--proxy-server=http://${config.proxy.address}:${config.proxy.port}`); } const browser = await puppeteer.launch({ args, defaultViewport: { - height: Config.page.height, - width: Config.page.width + height: config.page.height, + width: config.page.width }, - headless: Config.browser.isHeadless + headless: config.browser.isHeadless }); const promises = []; for (const store of Stores) { - Logger.debug(store.links); + logger.debug(store.links); if (store.setupAction !== undefined) { store.setupAction(browser); } @@ -73,6 +73,6 @@ async function main() { try { void main(); } catch (error) { - Logger.error('✖ something bad happened, resetting nvidia-snatcher', error); + logger.error('✖ something bad happened, resetting nvidia-snatcher', error); void main(); } diff --git a/src/logger.ts b/src/logger.ts index 24c8670..f508c09 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,7 +1,7 @@ import {Link, Store} from './store/model'; import winston, {format} from 'winston'; -import {Config} from './config'; import chalk from 'chalk'; +import {config} from './config'; const prettyJson = format.printf(info => { const timestamp = new Date().toLocaleTimeString(); @@ -13,7 +13,7 @@ const prettyJson = format.printf(info => { return chalk.grey(`[${timestamp}]`) + ` ${info.level} ` + chalk.grey('::') + ` ${info.message}`; }); -export const Logger = winston.createLogger({ +export const logger = winston.createLogger({ format: format.combine( format.colorize(), format.prettyPrint(), @@ -21,7 +21,7 @@ export const Logger = winston.createLogger({ format.simple(), prettyJson ), - level: Config.logLevel, + level: config.logLevel, transports: [new winston.transports.Console({})] }); @@ -76,10 +76,10 @@ export const Print = { }, maxPrice(link: Link, store: Store, price: number, color?: boolean): string { if (color) { - return '✖ ' + buildProductString(link, store, true) + ' :: ' + chalk.yellow(`PRICE ${price} EXCEEDS LIMIT ${Config.store.maxPrice}`); + return '✖ ' + buildProductString(link, store, true) + ' :: ' + chalk.yellow(`PRICE ${price} EXCEEDS LIMIT ${config.store.maxPrice}`); } - return `✖ ${buildProductString(link, store)} :: PRICE ${price} EXCEEDS LIMIT ${Config.store.maxPrice}`; + return `✖ ${buildProductString(link, store)} :: PRICE ${price} EXCEEDS LIMIT ${config.store.maxPrice}`; }, message(message: string, topic: string, store: Store, color?: boolean): string { if (color) { diff --git a/src/notification/desktop.ts b/src/notification/desktop.ts index 38de6fa..519ca10 100644 --- a/src/notification/desktop.ts +++ b/src/notification/desktop.ts @@ -1,14 +1,20 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; +import {Print, logger} from '../logger'; +import {config} from '../config'; import notifier from 'node-notifier'; -export function sendDesktopNotification(link: Link, store: Store) { - (async () => { - notifier.notify({ - message: link.cartUrl ? link.cartUrl : link.url, - title: Print.inStock(link, store) - }); +const desktop = config.notifications.desktop; - Logger.info('✔ desktop notification sent'); - })(); +export function sendDesktopNotification(link: Link, store: Store) { + if (desktop) { + logger.debug('↗ sending desktop notification'); + (async () => { + notifier.notify({ + message: link.cartUrl ? link.cartUrl : link.url, + title: Print.inStock(link, store) + }); + + logger.info('✔ desktop notification sent'); + })(); + } } diff --git a/src/notification/discord.ts b/src/notification/discord.ts index 0c5601b..c6bcd4f 100644 --- a/src/notification/discord.ts +++ b/src/notification/discord.ts @@ -1,38 +1,43 @@ import {Link, Store} from '../store/model'; import {MessageBuilder, Webhook} from 'discord-webhook-node'; -import {Config} from '../config'; -import {Logger} from '../logger'; +import {config} from '../config'; +import {logger} from '../logger'; -const hooks = Config.notifications.discord.webHookUrl; -const notifyGroup = Config.notifications.discord.notifyGroup; +const discord = config.notifications.discord; +const hooks = discord.webHookUrl; +const notifyGroup = discord.notifyGroup; export function sendDiscordMessage(link: Link, store: Store) { - (async () => { - try { - const embed = new MessageBuilder(); - embed.setTitle('Stock Notification'); - embed.addField('URL', link.cartUrl ? link.cartUrl : link.url, true); - embed.addField('Store', store.name, true); - embed.addField('Brand', link.brand, true); - embed.addField('Model', link.model, true); + if (discord.webHookUrl.length > 0) { + logger.debug('↗ sending discord message'); - if (notifyGroup) { - embed.setText(notifyGroup.join(' ')); + (async () => { + try { + const embed = new MessageBuilder(); + embed.setTitle('Stock Notification'); + embed.addField('URL', link.cartUrl ? link.cartUrl : link.url, true); + embed.addField('Store', store.name, true); + embed.addField('Brand', link.brand, true); + embed.addField('Model', link.model, true); + + if (notifyGroup) { + embed.setText(notifyGroup.join(' ')); + } + + embed.setColor(0x76B900); + embed.setTimestamp(); + + const promises = []; + for (const hook of hooks) { + promises.push(new Webhook(hook).send(embed)); + } + + await Promise.all(promises); + + logger.info('✔ discord message sent'); + } catch (error) { + logger.error('✖ couldn\'t send discord message', error); } - - embed.setColor(0x76B900); - embed.setTimestamp(); - - const promises = []; - for (const hook of hooks) { - promises.push(new Webhook(hook).send(embed)); - } - - await Promise.all(promises); - - Logger.info('✔ discord message sent'); - } catch (error) { - Logger.error('✖ couldn\'t send discord message', error); - } - })(); + })(); + } } diff --git a/src/notification/email.ts b/src/notification/email.ts index 6457249..ae14ea9 100644 --- a/src/notification/email.ts +++ b/src/notification/email.ts @@ -1,10 +1,10 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import Mail from 'nodemailer/lib/mailer'; +import {config} from '../config'; import nodemailer from 'nodemailer'; -const email = Config.notifications.email; +const email = config.notifications.email; const transporter = nodemailer.createTransport({ auth: { @@ -15,24 +15,28 @@ const transporter = nodemailer.createTransport({ }); export function sendEmail(link: Link, store: Store) { - const mailOptions: Mail.Options = { - attachments: link.screenshot ? [ - { - filename: link.screenshot, - path: `./${link.screenshot}` - } - ] : undefined, - from: email.username, - subject: Print.inStock(link, store), - text: link.cartUrl ? link.cartUrl : link.url, - to: email.to - }; + if (email.username && email.password) { + logger.debug('↗ sending email'); - transporter.sendMail(mailOptions, error => { - if (error) { - Logger.error('✖ couldn\'t send email', error); - } else { - Logger.info('✔ email sent'); - } - }); + const mailOptions: Mail.Options = { + attachments: link.screenshot ? [ + { + filename: link.screenshot, + path: `./${link.screenshot}` + } + ] : undefined, + from: email.username, + subject: Print.inStock(link, store), + text: link.cartUrl ? link.cartUrl : link.url, + to: email.to + }; + + transporter.sendMail(mailOptions, error => { + if (error) { + logger.error('✖ couldn\'t send email', error); + } else { + logger.info('✔ email sent'); + } + }); + } } diff --git a/src/notification/notification.ts b/src/notification/notification.ts index d3d56fc..6d75e20 100644 --- a/src/notification/notification.ts +++ b/src/notification/notification.ts @@ -1,11 +1,9 @@ import {Link, Store} from '../store/model'; -import {Config} from '../config'; -import {Logger} from '../logger'; import {playSound} from './sound'; import {sendDesktopNotification} from './desktop'; import {sendDiscordMessage} from './discord'; import {sendEmail} from './email'; -import {sendPushBulletNotification} from './pushbullet'; +import {sendPushbulletNotification} from './pushbullet'; import {sendPushoverNotification} from './pushover'; import {sendSMS} from './sms'; import {sendSlackMessage} from './slack'; @@ -13,69 +11,16 @@ import {sendTelegramMessage} from './telegram'; import {sendTweet} from './twitter'; import {sendTwilioMessage} from './twilio'; -const notifications = Config.notifications; - export function sendNotification(link: Link, store: Store) { - if (notifications.email.username && notifications.email.password) { - Logger.debug('↗ sending email'); - sendEmail(link, store); - } - - if (notifications.phone.number) { - Logger.debug('↗ sending sms'); - const carrier = notifications.phone.carrier; - if (carrier && notifications.phone.availableCarriers.has(carrier)) { - sendSMS(link, store); - } - } - - if (notifications.playSound) { - Logger.debug('↗ playing sound'); - playSound(); - } - - if (notifications.desktop) { - Logger.debug('↗ sending desktop notification'); - sendDesktopNotification(link, store); - } - - if (notifications.discord.webHookUrl.length > 0) { - Logger.debug('↗ sending discord message'); - sendDiscordMessage(link, store); - } - - if (notifications.slack.channel && notifications.slack.token) { - Logger.debug('↗ sending slack message'); - sendSlackMessage(link, store); - } - - if (notifications.telegram.accessToken && notifications.telegram.chatId) { - Logger.debug('↗ sending telegram message'); - sendTelegramMessage(link, store); - } - - if (notifications.twilio.accountSid && notifications.twilio.authToken) { - Logger.debug('↗ sending twilio message'); - sendTwilioMessage(link, store); - } - - if (notifications.pushBulletApiKey) { - Logger.debug('↗ sending pushbullet message'); - sendPushBulletNotification(link, store); - } - - if (notifications.pushover.token && notifications.pushover.username) { - Logger.debug('↗ sending pushover message'); - sendPushoverNotification(link, store); - } - - if ( - notifications.twitter.accessTokenKey && - notifications.twitter.accessTokenSecret && - notifications.twitter.consumerKey && - notifications.twitter.consumerSecret - ) { - Logger.debug('↗ sending twitter message'); - sendTweet(link, store); - } + sendEmail(link, store); + sendSMS(link, store); + playSound(); + sendDesktopNotification(link, store); + sendDiscordMessage(link, store); + sendSlackMessage(link, store); + sendTelegramMessage(link, store); + sendTwilioMessage(link, store); + sendPushbulletNotification(link, store); + sendPushoverNotification(link, store); + sendTweet(link, store); } diff --git a/src/notification/pushbullet.ts b/src/notification/pushbullet.ts index 522ca2b..ec1e70e 100644 --- a/src/notification/pushbullet.ts +++ b/src/notification/pushbullet.ts @@ -1,22 +1,26 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; -import PushBullet from 'pushbullet'; +import {Print, logger} from '../logger'; +import PushBullet from '@hijef/pushbullet'; +import {config} from '../config'; -const pushBulletApiKey = Config.notifications.pushBulletApiKey; +const pushbullet = config.notifications.pushbullet; -export function sendPushBulletNotification(link: Link, store: Store) { - const pusher = new PushBullet(pushBulletApiKey); +export function sendPushbulletNotification(link: Link, store: Store) { + if (pushbullet) { + logger.debug('↗ sending pushbullet message'); - pusher.note( - {}, - Print.inStock(link, store), - link.cartUrl ? link.cartUrl : link.url, - (error: Error) => { - if (error) { - Logger.error('✖ couldn\'t send pushbullet message', error); - } else { - Logger.info('✔ pushbullet message sent'); - } - }); + const pusher = new PushBullet(pushbullet); + + pusher.note( + {}, + Print.inStock(link, store), + link.cartUrl ? link.cartUrl : link.url, + (error: Error) => { + if (error) { + logger.error('✖ couldn\'t send pushbullet message', error); + } else { + logger.info('✔ pushbullet message sent'); + } + }); + } } diff --git a/src/notification/pushover.ts b/src/notification/pushover.ts index 2c08785..07c1ca1 100644 --- a/src/notification/pushover.ts +++ b/src/notification/pushover.ts @@ -1,26 +1,30 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import Push from 'pushover-notifications'; +import {config} from '../config'; -const pushover = Config.notifications.pushover; +const pushover = config.notifications.pushover; const push = new Push({ token: pushover.token, user: pushover.username }); export function sendPushoverNotification(link: Link, store: Store) { - const message = { - message: link.cartUrl ? link.cartUrl : link.url, - priority: pushover.priority, - title: Print.inStock(link, store) - }; + if (pushover.token && pushover.username) { + logger.debug('↗ sending pushover message'); - push.send(message, (error: Error) => { - if (error) { - Logger.error('✖ couldn\'t send pushover message', error); - } else { - Logger.info('✔ pushover message sent'); - } - }); + const message = { + message: link.cartUrl ? link.cartUrl : link.url, + priority: pushover.priority, + title: Print.inStock(link, store) + }; + + push.send(message, (error: Error) => { + if (error) { + logger.error('✖ couldn\'t send pushover message', error); + } else { + logger.info('✔ pushover message sent'); + } + }); + } } diff --git a/src/notification/slack.ts b/src/notification/slack.ts index c3b83e4..9deb069 100644 --- a/src/notification/slack.ts +++ b/src/notification/slack.ts @@ -1,30 +1,35 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import {WebClient} from '@slack/web-api'; +import {config} from '../config'; -const channel = Config.notifications.slack.channel; -const token = Config.notifications.slack.token; +const slack = config.notifications.slack; +const channel = slack.channel; +const token = slack.token; const web = new WebClient(token); export function sendSlackMessage(link: Link, store: Store) { - (async () => { - const givenUrl = link.cartUrl ? link.cartUrl : link.url; + if (slack.channel && slack.token) { + logger.debug('↗ sending slack message'); - try { - const result = await web.chat.postMessage({ - channel, - text: `${Print.inStock(link, store)}\n${givenUrl}` - }); + (async () => { + const givenUrl = link.cartUrl ? link.cartUrl : link.url; - if (!result.ok) { - Logger.error('✖ couldn\'t send slack message', result); - return; + try { + const result = await web.chat.postMessage({ + channel, + text: `${Print.inStock(link, store)}\n${givenUrl}` + }); + + if (!result.ok) { + logger.error('✖ couldn\'t send slack message', result); + return; + } + + logger.info('✔ slack message sent'); + } catch (error) { + logger.error('✖ couldn\'t send slack message', error); } - - Logger.info('✔ slack message sent'); - } catch (error) { - Logger.error('✖ couldn\'t send slack message', error); - } - })(); + })(); + } } diff --git a/src/notification/sms.ts b/src/notification/sms.ts index 9fc3100..01ae1c4 100644 --- a/src/notification/sms.ts +++ b/src/notification/sms.ts @@ -1,14 +1,14 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import Mail from 'nodemailer/lib/mailer'; +import {config} from '../config'; import nodemailer from 'nodemailer'; -if (Config.notifications.phone.number && !Config.notifications.email.username) { - Logger.warn('✖ in order to recieve sms alerts, email notifications must also be configured'); +if (config.notifications.phone.number && !config.notifications.email.username) { + logger.warn('✖ in order to recieve sms alerts, email notifications must also be configured'); } -const [email, phone] = [Config.notifications.email, Config.notifications.phone]; +const [email, phone] = [config.notifications.email, config.notifications.phone]; const transporter = nodemailer.createTransport({ auth: { @@ -19,26 +19,33 @@ const transporter = nodemailer.createTransport({ }); export function sendSMS(link: Link, store: Store) { - const mailOptions: Mail.Options = { - attachments: link.screenshot ? [ - { - filename: link.screenshot, - path: `./${link.screenshot}` - } - ] : undefined, - from: email.username, - subject: Print.inStock(link, store, false, true), - text: link.cartUrl ? link.cartUrl : link.url, - to: generateAddress() - }; + if (phone.number) { + logger.debug('↗ sending sms'); + const carrier = phone.carrier; - transporter.sendMail(mailOptions, error => { - if (error) { - Logger.error('✖ couldn\'t send sms', error); - } else { - Logger.info('✔ sms sent'); + if (carrier && phone.availableCarriers.has(carrier)) { + const mailOptions: Mail.Options = { + attachments: link.screenshot ? [ + { + filename: link.screenshot, + path: `./${link.screenshot}` + } + ] : undefined, + from: email.username, + subject: Print.inStock(link, store, false, true), + text: link.cartUrl ? link.cartUrl : link.url, + to: generateAddress() + }; + + transporter.sendMail(mailOptions, error => { + if (error) { + logger.error('✖ couldn\'t send sms', error); + } else { + logger.info('✔ sms sent'); + } + }); } - }); + } } function generateAddress() { @@ -48,5 +55,5 @@ function generateAddress() { return [phone.number, phone.availableCarriers.get(carrier)].join('@'); } - Logger.error('✖ unknown carrier', carrier); + logger.error('✖ unknown carrier', carrier); } diff --git a/src/notification/sound.ts b/src/notification/sound.ts index 49f20b2..082fa8f 100644 --- a/src/notification/sound.ts +++ b/src/notification/sound.ts @@ -1,35 +1,37 @@ -import {Config} from '../config'; -import {Logger} from '../logger'; +import {config} from '../config'; import fs from 'fs'; +import {logger} from '../logger'; import playerLib from 'play-sound'; let player: any; -if (Config.notifications.playSound) { +if (config.notifications.playSound) { player = playerLib(); if (player.player === null) { - Logger.warn('✖ couldn\'t find sound player'); + logger.warn('✖ couldn\'t find sound player'); } else { const playerName: string = player.player; - Logger.info(`✔ sound player found: ${playerName}`); + logger.info(`✔ sound player found: ${playerName}`); } } export function playSound() { - if (player.player !== null) { - fs.access(Config.notifications.playSound, fs.constants.F_OK, error => { + if (config.notifications.playSound && player.player !== null) { + logger.debug('↗ playing sound'); + + fs.access(config.notifications.playSound, fs.constants.F_OK, error => { if (error) { - Logger.error(`✖ error opening sound file: ${error.message}`); + logger.error(`✖ error opening sound file: ${error.message}`); return; } - player.play(Config.notifications.playSound, (error: Error) => { + player.play(config.notifications.playSound, (error: Error) => { if (error) { - Logger.error('✖ couldn\'t play sound', error); + logger.error('✖ couldn\'t play sound', error); } - Logger.info('✔ played sound'); + logger.info('✔ played sound'); }); }); } diff --git a/src/notification/telegram.ts b/src/notification/telegram.ts index bd67698..a697460 100644 --- a/src/notification/telegram.ts +++ b/src/notification/telegram.ts @@ -1,23 +1,27 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import {TelegramClient} from 'messaging-api-telegram'; +import {config} from '../config'; -const telegram = Config.notifications.telegram; +const telegram = config.notifications.telegram; const client = new TelegramClient({ accessToken: telegram.accessToken }); export function sendTelegramMessage(link: Link, store: Store) { - (async () => { - const givenUrl = link.cartUrl ? link.cartUrl : link.url; + if (telegram.accessToken && telegram.chatId) { + logger.debug('↗ sending telegram message'); - try { - await client.sendMessage(telegram.chatId, `${Print.inStock(link, store)}\n${givenUrl}`); - Logger.info('✔ telegram message sent'); - } catch (error) { - Logger.error('✖ couldn\'t send telegram message', error); - } - })(); + (async () => { + const givenUrl = link.cartUrl ? link.cartUrl : link.url; + + try { + await client.sendMessage(telegram.chatId, `${Print.inStock(link, store)}\n${givenUrl}`); + logger.info('✔ telegram message sent'); + } catch (error) { + logger.error('✖ couldn\'t send telegram message', error); + } + })(); + } } diff --git a/src/notification/twilio.ts b/src/notification/twilio.ts index a2cf6aa..608bb8b 100644 --- a/src/notification/twilio.ts +++ b/src/notification/twilio.ts @@ -1,25 +1,33 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; -import twilio from 'twilio'; +import {Print, logger} from '../logger'; +import {Twilio} from 'twilio'; +import {config} from '../config'; -const config = Config.notifications.twilio; +const twilio = config.notifications.twilio; +let client: Twilio; + +if (twilio.accountSid && twilio.authToken) { + client = new Twilio(twilio.accountSid, twilio.authToken); +} export function sendTwilioMessage(link: Link, store: Store) { - (async () => { - const givenUrl = link.cartUrl ? link.cartUrl : link.url; - const message = `${Print.inStock(link, store)}\n${givenUrl}`; + if (client) { + logger.debug('↗ sending twilio message'); - try { - const client = twilio(config.accountSid, config.authToken); - await client.messages.create({ - body: message, - from: config.from, - to: config.to - }); - Logger.info('✔ twilio message sent'); - } catch (error) { - Logger.error('✖ couldn\'t send twilio message', error); - } - })(); + (async () => { + const givenUrl = link.cartUrl ? link.cartUrl : link.url; + const message = `${Print.inStock(link, store)}\n${givenUrl}`; + + try { + await client.messages.create({ + body: message, + from: twilio.from, + to: twilio.to + }); + logger.info('✔ twilio message sent'); + } catch (error) { + logger.error('✖ couldn\'t send twilio message', error); + } + })(); + } } diff --git a/src/notification/twitter.ts b/src/notification/twitter.ts index 9d10a4d..620117a 100644 --- a/src/notification/twitter.ts +++ b/src/notification/twitter.ts @@ -1,9 +1,9 @@ import {Link, Store} from '../store/model'; -import {Logger, Print} from '../logger'; -import {Config} from '../config'; +import {Print, logger} from '../logger'; import Twitter from 'twitter'; +import {config} from '../config'; -const twitter = Config.notifications.twitter; +const twitter = config.notifications.twitter; const client = new Twitter({ access_token_key: twitter.accessTokenKey, @@ -13,17 +13,21 @@ const client = new Twitter({ }); export function sendTweet(link: Link, store: Store) { - let status = `${Print.inStock(link, store)}\n${link.cartUrl ? link.cartUrl : link.url}`; + if (twitter.accessTokenKey && twitter.accessTokenSecret && twitter.consumerKey && twitter.consumerSecret) { + logger.debug('↗ sending twitter message'); - if (twitter.tweetTags) { - status += `\n\n${twitter.tweetTags}`; - } + let status = `${Print.inStock(link, store)}\n${link.cartUrl ? link.cartUrl : link.url}`; - client.post('statuses/update', {status}, error => { - if (error) { - Logger.error('✖ couldn\'t send twitter notification', error); - } else { - Logger.info('✔ twitter notification sent'); + if (twitter.tweetTags) { + status += `\n\n${twitter.tweetTags}`; } - }); + + client.post('statuses/update', {status}, error => { + if (error) { + logger.error('✖ couldn\'t send twitter notification', error); + } else { + logger.info('✔ twitter notification sent'); + } + }); + } } diff --git a/src/store/fetch-links.ts b/src/store/fetch-links.ts index 2dcb4a3..0064d23 100644 --- a/src/store/fetch-links.ts +++ b/src/store/fetch-links.ts @@ -1,5 +1,5 @@ import {Link, Series, Store} from './model'; -import {Logger, Print} from '../logger'; +import {Print, logger} from '../logger'; import {Browser} from 'puppeteer'; import cheerio from 'cheerio'; import {filterSeries} from './filter'; @@ -7,7 +7,7 @@ import {usingResponse} from '../util'; function addNewLinks(store: Store, links: Link[], series: Series) { if (links.length === 0) { - Logger.error(Print.message('NO STORE LINKS FOUND', series, store, true)); + logger.error(Print.message('NO STORE LINKS FOUND', series, store, true)); return; } @@ -19,8 +19,8 @@ function addNewLinks(store: Store, links: Link[], series: Series) { return; } - Logger.info(Print.message(`FOUND ${newLinks.length} STORE LINKS`, series, store, true)); - Logger.debug(JSON.stringify(newLinks, null, 2)); + logger.info(Print.message(`FOUND ${newLinks.length} STORE LINKS`, series, store, true)); + logger.debug(JSON.stringify(newLinks, null, 2)); store.links = store.links.concat(newLinks); } @@ -37,13 +37,13 @@ export async function fetchLinks(store: Store, browser: Browser) { continue; } - Logger.info(Print.message('DETECTING STORE LINKS', series, store, true)); + logger.info(Print.message('DETECTING STORE LINKS', series, store, true)); promises.push(usingResponse(browser, url, async response => { const text = await response?.text(); if (!text) { - Logger.error(Print.message('NO RESPONSE', series, store, true)); + logger.error(Print.message('NO RESPONSE', series, store, true)); return; } diff --git a/src/store/filter.ts b/src/store/filter.ts index d44fbe6..93ad46b 100644 --- a/src/store/filter.ts +++ b/src/store/filter.ts @@ -1,5 +1,5 @@ -import {Config} from '../config'; import {Link} from './model'; +import {config} from '../config'; /** * Returns true if the brand should be checked for stock @@ -7,11 +7,11 @@ import {Link} from './model'; * @param brand The brand of the GPU */ function filterBrand(brand: Link['brand']): boolean { - if (Config.store.showOnlyBrands.length === 0) { + if (config.store.showOnlyBrands.length === 0) { return true; } - return Config.store.showOnlyBrands.includes(brand); + return config.store.showOnlyBrands.includes(brand); } /** @@ -20,12 +20,12 @@ function filterBrand(brand: Link['brand']): boolean { * @param model The model of the GPU */ function filterModel(model: Link['model']): boolean { - if (Config.store.showOnlyModels.length === 0) { + if (config.store.showOnlyModels.length === 0) { return true; } const sanitizedModel = model.replace(/\s/g, ''); - for (const configModel of Config.store.showOnlyModels) { + for (const configModel of config.store.showOnlyModels) { const sanitizedConfigModel = configModel.replace(/\s/g, ''); if (sanitizedModel === sanitizedConfigModel) { return true; @@ -41,11 +41,11 @@ function filterModel(model: Link['model']): boolean { * @param series The series of the GPU */ export function filterSeries(series: Link['series']): boolean { - if (Config.store.showOnlySeries.length === 0) { + if (config.store.showOnlySeries.length === 0) { return true; } - return Config.store.showOnlySeries.includes(series); + return config.store.showOnlySeries.includes(series); } /** diff --git a/src/store/includes-labels.ts b/src/store/includes-labels.ts index 0f84f06..e48d4dd 100644 --- a/src/store/includes-labels.ts +++ b/src/store/includes-labels.ts @@ -1,6 +1,6 @@ import {Element, LabelQuery, Pricing} from './model'; -import {Logger} from '../logger'; import {Page} from 'puppeteer'; +import {logger} from '../logger'; export type Selector = { requireVisible: boolean; @@ -44,7 +44,7 @@ export async function pageIncludesLabels(page: Page, query: LabelQuery, options: return false; } - Logger.debug(contents); + logger.debug(contents); return includesLabels(contents, query.text); })); @@ -103,7 +103,7 @@ export async function cardPriceLimit(page: Page, query: Pricing, max: number, op const priceSeperator = query.euroFormat ? /\./g : /,/g; const cardpriceNumber = Number.parseFloat(cardPrice.replace(priceSeperator, '').match(/\d+/g)!.join('.')); - Logger.debug(`Raw card price: ${cardPrice} | Limit: ${max}`); + logger.debug(`Raw card price: ${cardPrice} | Limit: ${max}`); return cardpriceNumber > max ? cardpriceNumber : null; } diff --git a/src/store/lookup.ts b/src/store/lookup.ts index 1bb8c76..7bc9deb 100644 --- a/src/store/lookup.ts +++ b/src/store/lookup.ts @@ -1,9 +1,9 @@ import {Browser, Page, Response} from 'puppeteer'; import {Link, Store} from './model'; -import {Logger, Print} from '../logger'; +import {Print, logger} from '../logger'; import {Selector, cardPriceLimit, pageIncludesLabels} from './includes-labels'; import {closePage, delay, getSleepTime, isStatusCodeInRange} from '../util'; -import {Config} from '../config'; +import {config} from '../config'; import {disableBlockerInPage} from '../adblocker'; import {filterStoreLink} from './filter'; import open from 'open'; @@ -27,20 +27,20 @@ async function lookup(browser: Browser, store: Store) { continue; } - if (Config.page.inStockWaitTime && inStock[link.url]) { - Logger.info(Print.inStockWaiting(link, store, true)); + if (config.page.inStockWaitTime && inStock[link.url]) { + logger.info(Print.inStockWaiting(link, store, true)); continue; } const page = await browser.newPage(); - page.setDefaultNavigationTimeout(Config.page.navigationTimeout); - await page.setUserAgent(Config.page.userAgent); + page.setDefaultNavigationTimeout(config.page.timeout); + await page.setUserAgent(config.page.userAgent); if (store.disableAdBlocker) { try { await disableBlockerInPage(page); } catch (error) { - Logger.error(error); + logger.error(error); } } @@ -49,7 +49,7 @@ async function lookup(browser: Browser, store: Store) { try { statusCode = await lookupCard(browser, store, page, link); } catch (error) { - Logger.error(`✖ [${store.name}] ${link.brand} ${link.model} - ${error.message as string}`); + logger.error(`✖ [${store.name}] ${link.brand} ${link.model} - ${error.message as string}`); } // Must apply backoff before closing the page, e.g. if CloudFlare is @@ -67,16 +67,16 @@ async function lookupCard(browser: Browser, store: Store, page: Page, link: Link const response: Response | null = await page.goto(link.url, {waitUntil: givenWaitFor}); if (!response) { - Logger.debug(Print.noResponse(link, store, true)); + logger.debug(Print.noResponse(link, store, true)); } const successStatusCodes = store.successStatusCodes ?? [[0, 399]]; const statusCode = response?.status() ?? 0; if (!isStatusCodeInRange(statusCode, successStatusCodes)) { if (statusCode === 429) { - Logger.warn(Print.rateLimit(link, store, true)); + logger.warn(Print.rateLimit(link, store, true)); } else { - Logger.warn(Print.badStatusCode(link, store, statusCode, true)); + logger.warn(Print.badStatusCode(link, store, statusCode, true)); } return statusCode; @@ -84,9 +84,9 @@ async function lookupCard(browser: Browser, store: Store, page: Page, link: Link if (await lookupCardInStock(store, page, link)) { const givenUrl = link.cartUrl ? link.cartUrl : link.url; - Logger.info(`${Print.inStock(link, store, true)}\n${givenUrl}`); + logger.info(`${Print.inStock(link, store, true)}\n${givenUrl}`); - if (Config.browser.open) { + if (config.browser.open) { if (link.openCartAction === undefined) { await open(givenUrl); } else { @@ -96,16 +96,16 @@ async function lookupCard(browser: Browser, store: Store, page: Page, link: Link sendNotification(link, store); - if (Config.page.inStockWaitTime) { + if (config.page.inStockWaitTime) { inStock[link.url] = true; setTimeout(() => { inStock[link.url] = false; - }, 1000 * Config.page.inStockWaitTime); + }, 1000 * config.page.inStockWaitTime); } - if (Config.page.screenshot) { - Logger.debug('ℹ saving screenshot'); + if (config.page.screenshot) { + logger.debug('ℹ saving screenshot'); link.screenshot = `success-${Date.now()}.png`; await page.screenshot({path: link.screenshot}); @@ -126,36 +126,36 @@ async function lookupCardInStock(store: Store, page: Page, link: Link) { const options = {...baseOptions, requireVisible: true, type: 'outerHTML' as const}; if (!await pageIncludesLabels(page, store.labels.inStock, options)) { - Logger.info(Print.outOfStock(link, store, true)); + logger.info(Print.outOfStock(link, store, true)); return false; } } if (store.labels.outOfStock) { if (await pageIncludesLabels(page, store.labels.outOfStock, baseOptions)) { - Logger.info(Print.outOfStock(link, store, true)); + logger.info(Print.outOfStock(link, store, true)); return false; } } if (store.labels.bannedSeller) { if (await pageIncludesLabels(page, store.labels.bannedSeller, baseOptions)) { - Logger.warn(Print.bannedSeller(link, store, true)); + logger.warn(Print.bannedSeller(link, store, true)); return false; } } if (store.labels.maxPrice) { - const priceLimit = await cardPriceLimit(page, store.labels.maxPrice, Config.store.maxPrice, baseOptions); + const priceLimit = await cardPriceLimit(page, store.labels.maxPrice, config.store.maxPrice, baseOptions); if (priceLimit) { - Logger.info(Print.maxPrice(link, store, priceLimit, true)); + logger.info(Print.maxPrice(link, store, priceLimit, true)); return false; } } if (store.labels.captcha) { if (await pageIncludesLabels(page, store.labels.captcha, baseOptions)) { - Logger.warn(Print.captcha(link, store, true)); + logger.warn(Print.captcha(link, store, true)); await delay(getSleepTime()); return false; } @@ -165,14 +165,14 @@ async function lookupCardInStock(store: Store, page: Page, link: Link) { } export async function tryLookupAndLoop(browser: Browser, store: Store) { - Logger.debug(`[${store.name}] Starting lookup...`); + logger.debug(`[${store.name}] Starting lookup...`); try { await lookup(browser, store); } catch (error) { - Logger.error(error); + logger.error(error); } const sleepTime = getSleepTime(); - Logger.debug(`[${store.name}] Lookup done, next one in ${sleepTime} ms`); + logger.debug(`[${store.name}] Lookup done, next one in ${sleepTime} ms`); setTimeout(tryLookupAndLoop, sleepTime, browser, store); } diff --git a/src/store/model/helpers/backoff.ts b/src/store/model/helpers/backoff.ts index af90109..621378a 100644 --- a/src/store/model/helpers/backoff.ts +++ b/src/store/model/helpers/backoff.ts @@ -1,7 +1,7 @@ import {Link, Store} from '..'; -import {Logger, Print} from '../../../logger'; +import {Print, logger} from '../../../logger'; import {delay, isStatusCodeInRange} from '../../../util'; -import {Config} from '../../../config'; +import {config} from '../../../config'; type Backoff = { count: number; @@ -27,26 +27,26 @@ export async function processBackoffDelay(store: Store, link: Link, statusCode: let backoff = stores[store.name]; if (!backoff) { - backoff = {count: 0, time: Config.browser.minBackoff}; + backoff = {count: 0, time: config.browser.minBackoff}; stores[store.name] = backoff; } if (!isBackoff) { if (backoff.count > 0) { backoff.count--; - backoff.time = Math.max(backoff.time / 2, Config.browser.minBackoff); + backoff.time = Math.max(backoff.time / 2, config.browser.minBackoff); } return -1; } const backoffTime = backoff.time; - Logger.debug(Print.backoff(link, store, {delay: backoffTime, statusCode}, true)); + logger.debug(Print.backoff(link, store, {delay: backoffTime, statusCode}, true)); await delay(backoff.time); backoff.count++; - backoff.time = Math.min(backoff.time * 2, Config.browser.maxBackoff); + backoff.time = Math.min(backoff.time * 2, config.browser.maxBackoff); return backoffTime; } diff --git a/src/store/model/helpers/nvidia-cart.ts b/src/store/model/helpers/nvidia-cart.ts index da2a9ea..f08e621 100644 --- a/src/store/model/helpers/nvidia-cart.ts +++ b/src/store/model/helpers/nvidia-cart.ts @@ -1,8 +1,8 @@ import {NvidiaRegionInfo, regionInfos} from '../nvidia-api'; import {usingPage, usingResponse} from '../../../util'; import {Browser} from 'puppeteer'; -import {Config} from '../../../config'; -import {Logger} from '../../../logger'; +import {config} from '../../../config'; +import {logger} from '../../../logger'; import open from 'open'; interface NvidiaSessionTokenJSON { @@ -34,7 +34,7 @@ export class NvidiaCart { await this.refreshSessionToken(); - setTimeout(callback, Config.nvidia.sessionTtl); + setTimeout(callback, config.nvidia.sessionTtl); }; this.isKeepAlive = true; @@ -47,7 +47,7 @@ export class NvidiaCart { } public get regionInfo(): NvidiaRegionInfo { - const country = Config.store.country; + const country = config.store.country; const regionInfo = regionInfos.get(country); if (!regionInfo) { throw new Error(`Unknown country ${country}`); @@ -62,20 +62,20 @@ export class NvidiaCart { public async addToCard(productId: number, name: string): Promise { let cartUrl: string | undefined; - Logger.info(`🚀🚀🚀 [nvidia] ${name}, starting auto add to cart 🚀🚀🚀`); + logger.info(`🚀🚀🚀 [nvidia] ${name}, starting auto add to cart 🚀🚀🚀`); try { - Logger.info(`🚀🚀🚀 [nvidia] ${name}, adding to cart 🚀🚀🚀`); + logger.info(`🚀🚀🚀 [nvidia] ${name}, adding to cart 🚀🚀🚀`); let lastError: Error | string | undefined; /* eslint-disable no-await-in-loop */ - for (let i = 0; i < Config.nvidia.addToCardAttempts; i++) { + for (let i = 0; i < config.nvidia.addToCardAttempts; i++) { try { cartUrl = await this.addToCartAndGetLocationRedirect(productId); break; } catch (error) { - Logger.error(`✖ [nvidia] ${name} could not automatically add to cart, attempt ${i + 1} of ${Config.nvidia.addToCardAttempts}`, error); - Logger.debug(error); + logger.error(`✖ [nvidia] ${name} could not automatically add to cart, attempt ${i + 1} of ${config.nvidia.addToCardAttempts}`, error); + logger.debug(error); lastError = error; } @@ -87,13 +87,13 @@ export class NvidiaCart { throw lastError; } - Logger.info(`🚀🚀🚀 [nvidia] ${name}, opening checkout page 🚀🚀🚀`); - Logger.info(cartUrl); + logger.info(`🚀🚀🚀 [nvidia] ${name}, opening checkout page 🚀🚀🚀`); + logger.info(cartUrl); await open(cartUrl); } catch (error) { - Logger.error(`✖ [nvidia] ${name} could not automatically add to cart, opening page`); - Logger.debug(error); + logger.error(`✖ [nvidia] ${name} could not automatically add to cart, opening page`); + logger.debug(error); cartUrl = this.fallbackCartUrl; @@ -116,7 +116,7 @@ export class NvidiaCart { } public async refreshSessionToken(): Promise { - Logger.debug('ℹ [nvidia] refreshing session token'); + logger.debug('ℹ [nvidia] refreshing session token'); try { const result = await usingResponse(this.browser, this.sessionUrl, async response => { return response?.json() as NvidiaSessionTokenJSON | undefined; @@ -126,10 +126,10 @@ export class NvidiaCart { } this.sessionToken = result.session_token; - Logger.debug(`ℹ [nvidia] session_token=${result.session_token}`); + logger.debug(`ℹ [nvidia] session_token=${result.session_token}`); } catch (error) { const message: string = typeof error === 'object' ? error.message : error; - Logger.error(`✖ [nvidia] ${message}`); + logger.error(`✖ [nvidia] ${message}`); } } @@ -137,7 +137,7 @@ export class NvidiaCart { const url = 'https://api-prod.nvidia.com/direct-sales-shop/DR/add-to-cart'; const sessionToken = await this.getSessionToken(); - Logger.info(`ℹ [nvidia] session_token=${sessionToken}`); + logger.info(`ℹ [nvidia] session_token=${sessionToken}`); const locationData = await usingPage(this.browser, async page => { page.removeAllListeners('request'); diff --git a/src/store/model/helpers/nvidia.ts b/src/store/model/helpers/nvidia.ts index f5b5b7e..2cd9743 100644 --- a/src/store/model/helpers/nvidia.ts +++ b/src/store/model/helpers/nvidia.ts @@ -1,12 +1,12 @@ import {NvidiaRegionInfo, regionInfos} from '../nvidia-api'; import {Browser} from 'puppeteer'; -import {Config} from '../../../config'; import {Link} from '../store'; import {NvidiaCart} from './nvidia-cart'; +import {config} from '../../../config'; import {timestampUrlParameter} from '../../timestamp-url-parameter'; function getRegionInfo(): NvidiaRegionInfo { - let country = Config.store.country; + let country = config.store.country; if (!regionInfos.has(country)) { country = 'usa'; } @@ -30,7 +30,7 @@ export function generateSetupAction() { return async (browser: Browser) => { cart = new NvidiaCart(browser); - if (Config.browser.open) { + if (config.browser.open) { cart.keepAlive(); } }; diff --git a/src/store/model/index.ts b/src/store/model/index.ts index b912d35..f2ee55d 100644 --- a/src/store/model/index.ts +++ b/src/store/model/index.ts @@ -8,11 +8,9 @@ import {AsusDe} from './asus-de'; import {BAndH} from './bandh'; import {BestBuy} from './bestbuy'; import {BestBuyCa} from './bestbuy-ca'; -import {Config} from '../../config'; import {Evga} from './evga'; import {EvgaEu} from './evga-eu'; import {Gamestop} from './gamestop'; -import {Logger} from '../../logger'; import {MicroCenter} from './microcenter'; import {Newegg} from './newegg'; import {NeweggCa} from './newegg-ca'; @@ -22,6 +20,8 @@ import {OfficeDepot} from './officedepot'; import {Pny} from './pny'; import {Store} from './store'; import {Zotac} from './zotac'; +import {config} from '../../config'; +import {logger} from '../../logger'; const masterList = new Map([ [Adorama.name, Adorama], @@ -49,27 +49,27 @@ const masterList = new Map([ const list = new Map(); -for (const name of Config.store.stores) { +for (const name of config.store.stores) { if (masterList.has(name)) { list.set(name, masterList.get(name)); } else { const logString = `No store named ${name}, skipping.`; - Logger.warn(logString); + logger.warn(logString); } } -Logger.info(`ℹ selected stores: ${Array.from(list.keys()).join(', ')}`); +logger.info(`ℹ selected stores: ${Array.from(list.keys()).join(', ')}`); -if (Config.store.showOnlyBrands.length > 0) { - Logger.info(`ℹ selected brands: ${Config.store.showOnlyBrands.join(', ')}`); +if (config.store.showOnlyBrands.length > 0) { + logger.info(`ℹ selected brands: ${config.store.showOnlyBrands.join(', ')}`); } -if (Config.store.showOnlyModels.length > 0) { - Logger.info(`ℹ selected models: ${Config.store.showOnlyModels.join(', ')}`); +if (config.store.showOnlyModels.length > 0) { + logger.info(`ℹ selected models: ${config.store.showOnlyModels.join(', ')}`); } -if (Config.store.showOnlySeries.length > 0) { - Logger.info(`ℹ selected series: ${Config.store.showOnlySeries.join(', ')}`); +if (config.store.showOnlySeries.length > 0) { + logger.info(`ℹ selected series: ${config.store.showOnlySeries.join(', ')}`); } export const Stores = Array.from(list.values()) as Store[]; diff --git a/src/store/model/microcenter.ts b/src/store/model/microcenter.ts index 8a1ae62..833ae81 100644 --- a/src/store/model/microcenter.ts +++ b/src/store/model/microcenter.ts @@ -1,7 +1,8 @@ -import {Config} from '../../config'; import {Store} from './store'; +import {config} from '../../config'; + +const microCenterLocation = config.store.microCenterLocation; -const MicroCenterLocation = Config.store.microCenterLocation; const microCenterLocationToId: Map = new Map([ ['web', '029'], ['brooklyn', '115'], @@ -32,10 +33,10 @@ const microCenterLocationToId: Map = new Map([ ]); let storeId: string; -if (microCenterLocationToId.get(MicroCenterLocation) === undefined) { +if (microCenterLocationToId.get(microCenterLocation) === undefined) { storeId = '029'; } else { - storeId = microCenterLocationToId.get(MicroCenterLocation)!; + storeId = microCenterLocationToId.get(microCenterLocation)!; } export const MicroCenter: Store = { diff --git a/src/types/pushbullet.d.ts b/src/types/pushbullet.d.ts index c7126e8..5f82479 100644 --- a/src/types/pushbullet.d.ts +++ b/src/types/pushbullet.d.ts @@ -1 +1 @@ -declare module 'pushbullet'; +declare module '@hijef/pushbullet'; diff --git a/src/util.ts b/src/util.ts index 0a983d3..24d30f3 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,11 +1,11 @@ import {Browser, Page, Response} from 'puppeteer'; -import {Config} from './config'; -import {Logger} from './logger'; import {StatusCodeRangeArray} from './store/model'; +import {config} from './config'; import {disableBlockerInPage} from './adblocker'; +import {logger} from './logger'; export function getSleepTime() { - return Config.browser.minSleep + (Math.random() * (Config.browser.maxSleep - Config.browser.minSleep)); + return config.browser.minSleep + (Math.random() * (config.browser.maxSleep - config.browser.minSleep)); } export async function delay(ms: number) { @@ -47,8 +47,8 @@ export async function usingResponse( export async function usingPage(browser: Browser, cb: (page: Page, browser: Browser) => Promise): Promise { const page = await browser.newPage(); - page.setDefaultNavigationTimeout(Config.page.navigationTimeout); - await page.setUserAgent(Config.page.userAgent); + page.setDefaultNavigationTimeout(config.page.timeout); + await page.setUserAgent(config.page.userAgent); try { return await cb(page, browser); @@ -56,13 +56,13 @@ export async function usingPage(browser: Browser, cb: (page: Page, browser: B try { await closePage(page); } catch (error) { - Logger.error(error); + logger.error(error); } } } export async function closePage(page: Page) { - if (!Config.browser.lowBandwidth) { + if (!config.browser.lowBandwidth) { await disableBlockerInPage(page); }