From 5f017c6a828cb4e76aa1506ed16ce7c0296a92c3 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Fri, 30 Apr 2021 00:13:02 -0500 Subject: [PATCH 01/19] wip --- package-lock.json | 5220 ++++++++++++++++++++++++++++++++++++++++- package.json | 1 + src/index.js | 37 +- src/manager.js | 138 +- src/plans.js | 28 +- src/worker.js | 7 +- test/singletonTest.js | 15 + 7 files changed, 5386 insertions(+), 60 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8f247cb2..0949dcff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,8 +1,5205 @@ { "name": "pg-boss", "version": "5.2.3", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, + "packages": { + "": { + "version": "5.2.3", + "license": "MIT", + "dependencies": { + "cron-parser": "^3.3.0", + "delay": "^5.0.0", + "lodash.debounce": "^4.0.8", + "p-map": "^4.0.0", + "pg": "^8.5.1", + "uuid": "^8.3.2" + }, + "devDependencies": { + "coveralls": "^3.1.0", + "luxon": "^1.26.0", + "mocha": "^8.3.2", + "nyc": "^15.1.0", + "standard": "^16.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", + "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.1" + } + }, + "node_modules/@babel/core": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", + "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.2", + "@babel/helper-module-transforms": "^7.10.1", + "@babel/helpers": "^7.10.1", + "@babel/parser": "^7.10.2", + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@babel/generator": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", + "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", + "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", + "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", + "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", + "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", + "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.1", + "@babel/helper-replace-supers": "^7.10.1", + "@babel/helper-simple-access": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1", + "lodash": "^4.17.13" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", + "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", + "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.10.1", + "@babel/helper-optimise-call-expression": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", + "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", + "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", + "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "dev": true + }, + "node_modules/@babel/helpers": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", + "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.1", + "@babel/traverse": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/highlight": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", + "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", + "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", + "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1" + } + }, + "node_modules/@babel/traverse": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", + "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.1", + "@babel/generator": "^7.10.1", + "@babel/helper-function-name": "^7.10.1", + "@babel/helper-split-export-declaration": "^7.10.1", + "@babel/parser": "^7.10.1", + "@babel/types": "^7.10.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@babel/types": { + "version": "7.10.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", + "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.1", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", + "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-includes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", + "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "get-intrinsic": "^1.0.1", + "is-string": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", + "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/convert-source-map/node_modules/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 + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/coveralls": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.0.tgz", + "integrity": "sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/coveralls/node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/cron-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.3.0.tgz", + "integrity": "sha512-Tz5WxSrDVhR7YVuLuUxhXoMGHCWoe8I7g8APkyRZNaINXHQ3zcfK97av6hBYy9ue4sOLI7ZH7SeQqi/t4jR+5A==", + "dependencies": { + "is-nan": "^1.3.0", + "luxon": "^1.25.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.13.0.tgz", + "integrity": "sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/eslint-config-standard": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", + "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", + "dev": true + }, + "node_modules/eslint-config-standard-jsx": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-10.0.0.tgz", + "integrity": "sha512-hLeA2f5e06W1xyr/93/QJulN/rLbUVUmqTlexv9PRKHFwEC9ffJcH2LvJhMoEqYQBEYafedgGZXH2W8NUpt5lA==", + "dev": true + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "dependencies": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-module-utils/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-module-utils/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", + "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", + "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flatmap": "^1.2.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "object.entries": "^1.1.2", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "resolve": "^1.18.1", + "string.prototype.matchall": "^4.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "dev": true, + "dependencies": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/fromentries": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", + "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "dependencies": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hasha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", + "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "dependencies": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internal-slot/node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/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 + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", + "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.2", + "object.assign": "^4.1.2" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/lcov-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz", + "integrity": "sha1-6w1GtUER68VhrLTECO+TY73I9+A=", + "dev": true, + "bin": { + "lcov-parse": "bin/cli.js" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/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, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", + "dev": true, + "engines": { + "node": ">=0.8.6" + } + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/luxon": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.26.0.tgz", + "integrity": "sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A==", + "engines": { + "node": "*" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", + "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" + }, + "bin": { + "nyc": "bin/nyc.js" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "dependencies": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/nyc/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nyc/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "node_modules/nyc/node_modules/yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", + "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", + "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/pg": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", + "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.4.0", + "pg-pool": "^3.2.2", + "pg-protocol": "^1.4.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/pg-connection-string": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", + "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", + "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + }, + "node_modules/pg-protocol": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", + "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", + "dependencies": { + "split2": "^3.1.1" + } + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/regexp.prototype.flags/node_modules/es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "dependencies": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.3.tgz", + "integrity": "sha512-70F7NH0hSkNXosXRltjSv6KpTAOkUkSfyu3ynyM5dtRUiLtR+yX9EGZ7RKwuGUqCJiX/cnkceVM6HTZ4JpaqDg==", + "dev": true, + "dependencies": { + "eslint": "~7.13.0", + "eslint-config-standard": "16.0.2", + "eslint-config-standard-jsx": "10.0.0", + "eslint-plugin-import": "~2.22.1", + "eslint-plugin-node": "~11.1.0", + "eslint-plugin-promise": "~4.2.1", + "eslint-plugin-react": "~7.21.5", + "standard-engine": "^14.0.1" + }, + "bin": { + "standard": "bin/cmd.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/standard-engine": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-14.0.1.tgz", + "integrity": "sha512-7FEzDwmHDOGva7r9ifOzD3BGdTbA7ujJ50afLVdW/tK14zQEptJjbFuUfn50irqdHDcTbNh0DTIoMPynMCXb0Q==", + "dev": true, + "dependencies": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.5", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8.10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", + "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", + "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", + "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + } + } + }, "dependencies": { "@babel/code-frame": { "version": "7.10.1", @@ -2264,6 +7461,11 @@ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", @@ -3662,6 +8864,14 @@ "xdg-basedir": "^4.0.0" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -3707,14 +8917,6 @@ "define-properties": "^1.1.3" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/package.json b/package.json index 6ca7f3f3..89bdd28b 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dependencies": { "cron-parser": "^3.3.0", "delay": "^5.0.0", + "lodash.debounce": "^4.0.8", "p-map": "^4.0.0", "pg": "^8.5.1", "uuid": "^8.3.2" diff --git a/src/index.js b/src/index.js index c8591bba..b6fb8425 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,7 @@ const Manager = require('./manager') const Timekeeper = require('./timekeeper') const Boss = require('./boss') const Db = require('./db') +const delay = require('delay') class PgBoss extends EventEmitter { static getConstructionPlans (schema) { @@ -103,20 +104,42 @@ class PgBoss extends EventEmitter { return this } - async stop () { - if (!this.isStarted) { + async stop ({ force }) { + if (!this.isStarted || this.stopping) { return } - await this.timekeeper.stop() + this.stopping = true + await this.manager.stop() - await this.boss.stop() - if (this.db.isOurs) { - await this.db.close() + const shutdown = async () => { + await this.timekeeper.stop() + await this.boss.stop() + + if (this.db.isOurs && force === true) { + await this.db.close() + } + + this.isStarted = false + this.stopping = false + } + + if (force) { + return await shutdown() } - this.isStarted = false + let iterations = 0 + + while (iterations < 10) { + if (this.manager.getWipData().length === 0) { + return await shutdown() + } + + await delay(5000) + + iterations++ + } } } diff --git a/src/manager.js b/src/manager.js index 463f9531..81af299e 100644 --- a/src/manager.js +++ b/src/manager.js @@ -2,15 +2,20 @@ const assert = require('assert') const EventEmitter = require('events') const pMap = require('p-map') const uuid = require('uuid') +const debounce = require('lodash.debounce') +const Attorney = require('./attorney') const Worker = require('./worker') + const plans = require('./plans') -const Attorney = require('./attorney') +const { COMPLETION_JOB_PREFIX } = plans -const completedJobPrefix = plans.completedJobPrefix +const WIP_EVENT_INTERVAL = 2000 +const WIP_DEBOUNCE_OPTIONS = { leading: true, trailing: true, maxWait: WIP_EVENT_INTERVAL } const events = { - error: 'error' + error: 'error', + wip: 'wip' } class Manager extends EventEmitter { @@ -53,7 +58,10 @@ class Manager extends EventEmitter { } async stop () { - Object.keys(this.subscriptions).forEach(name => this.unsubscribe(name)) + for (const sub of Object.values(this.subscriptions)) { + await this.unsubscribe(sub.name) + } + this.subscriptions = {} } @@ -64,63 +72,125 @@ class Manager extends EventEmitter { async onComplete (name, ...args) { const { options, callback } = Attorney.checkSubscribeArgs(name, args, this.config) - return this.watch(completedJobPrefix + name, options, callback) + return this.watch(COMPLETION_JOB_PREFIX + name, options, callback) + } + + getWipData () { + return Object.values(this.subscriptions) + .map(({ name, jobs }) => ({ name, count: jobs.size() })) + .filter(i => i.count > 0) + } + + emitWipThrottled () { + debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) + } + + registerWorker (name, worker) { + if (!this.subscriptions[name]) { + this.subscriptions[name] = { + name, + workers: [], + jobs: new Set() + } + } + + this.subscriptions[name].workers.push(worker) + } + + registerJobs (name, value) { + value = Array.isArray(value) ? value : [value] + + for (const job of value) { + this.subscriptions[name].jobs.add(job.id) + } + + this.emitWipThrottled() + } + + deregisterJobs (name, value) { + value = Array.isArray(value) ? value : [value] + + for (const jobId of value) { + this.subscriptions[name].jobs.delete(jobId) + } + + this.emitWipThrottled() + } + + async watchFinish (name, value, cb) { + try { + await cb() + this.deregisterJobs(name, value) + } catch (err) { + this.emit(events.error, err) + } + } + + async watchFail (name, value, data) { + await this.watchFinish(name, value, () => this.fail(value, data)) + } + + async watchComplete (name, value, data) { + await this.watchFinish(name, value, () => this.complete(value, data)) } async watch (name, options, callback) { - options.newJobCheckInterval = options.newJobCheckInterval || this.config.newJobCheckInterval + const { + newJobCheckInterval: interval = this.config.newJobCheckInterval, + batchSize, + teamSize = 1, + teamConcurrency = 1, + includeMetadata = false + } = options + + const id = uuid.v4() + + const fetch = () => this.fetch(name, batchSize || teamSize, { includeMetadata }) - const sendItBruh = async (jobs) => { + const onFetch = async (jobs) => { if (!jobs) { return } - // If you get a batch, for now you should use complete() so you can control - // whether individual or group completion responses apply to your use case + this.registerJobs(name, jobs) + // Failing will fail all fetched jobs - if (options.batchSize) { - return Promise.all([callback(jobs)]).catch(err => this.fail(jobs.map(job => job.id), err)) + if (batchSize) { + return await Promise.all([callback(jobs)]).catch(err => this.watchFail(name, jobs.map(job => job.id), err)) } - const concurrency = options.teamConcurrency || 1 - - // either no option was set, or teamSize was used - return pMap(jobs, job => + await pMap(jobs, job => callback(job) - .then(value => this.complete(job.id, value)) - .catch(err => this.fail(job.id, err)) - , { concurrency } + .then(result => this.watchComplete(name, job.id, result)) + .catch(err => this.watchFail(name, job.id, err)) + , { concurrency: teamConcurrency } ).catch(() => {}) // allow promises & non-promises to live together in harmony } - const fetchOptions = { includeMetadata: options.includeMetadata || false } - const onError = error => this.emit(events.error, error) - - const workerConfig = { - name, - fetch: () => this.fetch(name, options.batchSize || options.teamSize || 1, fetchOptions), - onFetch: jobs => sendItBruh(jobs), - onError, - interval: options.newJobCheckInterval + const onError = error => { + this.emit(events.error, { ...error, pgbossWorker: id, pgbossQueue: name }) } - const worker = new Worker(workerConfig) - worker.start() + const worker = new Worker({ id, name, fetch, onFetch, onError, interval }) - if (!this.subscriptions[name]) { this.subscriptions[name] = { workers: [] } } + this.registerWorker(worker) - this.subscriptions[name].workers.push(worker) + worker.start() } async unsubscribe (name) { assert(this.subscriptions[name], `No subscriptions for ${name} were found.`) + this.subscriptions[name].stopping = true + this.subscriptions[name].workers.forEach(worker => worker.stop()) - delete this.subscriptions[name] + + // todo: we need to wait until each worker is done before killing the map key + // delete this.subscriptions[name] } async offComplete (name) { - return this.unsubscribe(completedJobPrefix + name) + return this.unsubscribe(COMPLETION_JOB_PREFIX + name) } async publish (...args) { @@ -265,7 +335,7 @@ class Manager extends EventEmitter { } async fetchCompleted (name, batchSize, options = {}) { - return this.fetch(completedJobPrefix + name, batchSize, options) + return this.fetch(COMPLETION_JOB_PREFIX + name, batchSize, options) } mapCompletionIdArg (id, funcName) { diff --git a/src/plans.js b/src/plans.js index 437ad9e2..cd4c2bc3 100644 --- a/src/plans.js +++ b/src/plans.js @@ -8,7 +8,9 @@ const states = { failed: 'failed' } const assert = require('assert') -const completedJobPrefix = `__state__${states.completed}__` + +const COMPLETION_JOB_PREFIX = `__state__${states.completed}__` +const SINGLETON_QUEUE_KEY = '__pgboss__singleton_queue' const MUTEX = 1337968055000 const MIGRATE_RACE_MESSAGE = 'division by zero' @@ -42,7 +44,7 @@ module.exports = { getCronTime, setCronTime, states: { ...states }, - completedJobPrefix, + COMPLETION_JOB_PREFIX, locked, assertMigration, MIGRATE_RACE_MESSAGE, @@ -77,6 +79,7 @@ function create (schema, version) { createIndexSingletonOn(schema), createIndexSingletonKeyOn(schema), createIndexSingletonKey(schema), + createIndexSingletonQueue(schema), insertVersion(schema, version) ] @@ -216,6 +219,13 @@ function createIndexSingletonKeyOn (schema) { ` } +function createIndexSingletonQueue (schema) { + // "singleton queue" means "only 1 job can be queued at a time" + return ` + CREATE UNIQUE INDEX job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < '${states.active}' AND singletonOn IS NULL AND singletonKey = '${SINGLETON_QUEUE_KEY}' + ` +} + function createIndexJobName (schema) { return ` CREATE INDEX job_name ON ${schema}.job (name text_pattern_ops) @@ -350,11 +360,11 @@ function completeJobs (schema) { ), completion_jobs as ( INSERT INTO ${schema}.job (name, data, keepUntil) SELECT - '${completedJobPrefix}' || name, + '${COMPLETION_JOB_PREFIX}' || name, ${buildJsonCompletionObject(true)}, ${keepUntilInheritance} FROM results - WHERE NOT name LIKE '${completedJobPrefix}%' + WHERE NOT name LIKE '${COMPLETION_JOB_PREFIX}%' AND on_complete ) SELECT COUNT(*) FROM results @@ -378,12 +388,12 @@ function failJobs (schema) { ), completion_jobs as ( INSERT INTO ${schema}.job (name, data, keepUntil) SELECT - '${completedJobPrefix}' || name, + '${COMPLETION_JOB_PREFIX}' || name, ${buildJsonCompletionObject(true)}, ${keepUntilInheritance} FROM results WHERE state = '${states.failed}' - AND NOT name LIKE '${completedJobPrefix}%' + AND NOT name LIKE '${COMPLETION_JOB_PREFIX}%' AND on_complete ) SELECT COUNT(*) FROM results @@ -406,12 +416,12 @@ function expire (schema) { ) INSERT INTO ${schema}.job (name, data, keepUntil) SELECT - '${completedJobPrefix}' || name, + '${COMPLETION_JOB_PREFIX}' || name, ${buildJsonCompletionObject()}, ${keepUntilInheritance} FROM results WHERE state = '${states.expired}' - AND NOT name LIKE '${completedJobPrefix}%' + AND NOT name LIKE '${COMPLETION_JOB_PREFIX}%' AND on_complete ` } @@ -533,7 +543,7 @@ function countStates (schema) { return ` SELECT name, state, count(*) size FROM ${schema}.job - WHERE name NOT LIKE '${completedJobPrefix}%' + WHERE name NOT LIKE '${COMPLETION_JOB_PREFIX}%' GROUP BY rollup(name), rollup(state) ` } diff --git a/src/worker.js b/src/worker.js index 2098b206..ca64ba91 100644 --- a/src/worker.js +++ b/src/worker.js @@ -9,7 +9,12 @@ class Worker { while (!this.stopped) { const started = Date.now() - await this.config.fetch().then(this.config.onFetch).catch(this.config.onError) + try { + const jobs = await this.config.fetch() + await this.config.onFetch(jobs) + } catch (err) { + this.config.onError(err) + } const duration = Date.now() - started diff --git a/test/singletonTest.js b/test/singletonTest.js index 3ae4eb7f..f5735062 100644 --- a/test/singletonTest.js +++ b/test/singletonTest.js @@ -66,4 +66,19 @@ describe('singleton', function () { await boss.stop() }) + + it('publishOnce() without a key should also work', async function () { + const queue = 'publishOnceNoKey' + + const boss = await helper.start(this.test.bossConfig) + const jobId = await boss.publishOnce(queue) + + assert(jobId) + + const jobId2 = await boss.publishOnce(queue) + + assert.strictEqual(jobId2, null) + + await boss.stop() + }) }) From f8817a2714dbaffe1969ec7cce1fc05584e25004 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Fri, 30 Apr 2021 12:12:21 -0500 Subject: [PATCH 02/19] wip --- src/boss.js | 1 + src/index.js | 71 +++++++++++++++++++++++++++++++-------------- src/manager.js | 32 ++++++++++++++------ src/worker.js | 8 +++-- test/archiveTest.js | 6 ++-- test/testHelper.js | 2 ++ 6 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/boss.js b/src/boss.js index b7ab1eaf..52342c0f 100644 --- a/src/boss.js +++ b/src/boss.js @@ -29,6 +29,7 @@ class Boss extends EventEmitter { this.monitorIntervalSeconds = config.monitorStateIntervalSeconds } + this.queues = queues this.events = events this.expireCommand = plans.expire(config.schema) diff --git a/src/index.js b/src/index.js index b6fb8425..41a00edc 100644 --- a/src/index.js +++ b/src/index.js @@ -67,8 +67,9 @@ class PgBoss extends EventEmitter { function promoteFunction (obj, func) { this[func.name] = (...args) => { - if (!this.isStarted) { - return Promise.reject(new Error('pg-boss not started! Use start().')) + if (!this.isStarted || this.stoppingOn) { + const state = this.stoppingOn ? 'stopping' : 'stopped' + return Promise.reject(new Error(`pg-boss is ${state}.`)) } return func.apply(obj, args) @@ -104,42 +105,70 @@ class PgBoss extends EventEmitter { return this } - async stop ({ force }) { - if (!this.isStarted || this.stopping) { + async stop (options = {}) { + if (!this.isStarted || this.stoppingOn) { return } - this.stopping = true + let { graceful = true, timeout = 30000 } = options - await this.manager.stop() + timeout = Math.max(timeout, 1000) + + this.stoppingOn = Date.now() + + await this.manager.stop({ not: this.boss.queues.MAINTENANCE }) + await this.timekeeper.stop() + + let polling = false const shutdown = async () => { - await this.timekeeper.stop() - await this.boss.stop() - if (this.db.isOurs && force === true) { - await this.db.close() + try { + await this.boss.stop() + + if (this.db.isOurs) { + await this.db.close() + } + + } catch(err) { + + if(polling) { + this.emit('error', err) + } else { + throw err + } + + } finally { + + this.isStarted = false + this.stoppingOn = null + + this.emit('stopped') } + + } - this.isStarted = false - this.stopping = false + if (!graceful) { + return await shutdown() } - if (force) { + if (this.manager.getWipData().length === 0) { return await shutdown() } - let iterations = 0 + polling = true - while (iterations < 10) { - if (this.manager.getWipData().length === 0) { - return await shutdown() - } + setImmediate(async () => { + while (Date.now() - this.stoppingOn < timeout) { + await delay(2000) - await delay(5000) + if (this.manager.getWipData().length === 0) { + return await shutdown() + } + } - iterations++ - } + await shutdown() + }) } } diff --git a/src/manager.js b/src/manager.js index 81af299e..33bba9d8 100644 --- a/src/manager.js +++ b/src/manager.js @@ -57,12 +57,19 @@ class Manager extends EventEmitter { ] } - async stop () { - for (const sub of Object.values(this.subscriptions)) { - await this.unsubscribe(sub.name) + async stop (options = {}) { + + const { not = null } = options + + let subs = Object.values(this.subscriptions) + + if(not) { + subs = subs.filter(i => i.name !== not) } - this.subscriptions = {} + for (const sub of subs) { + await this.unsubscribe(sub.name) + } } async subscribe (name, ...args) { @@ -179,14 +186,21 @@ class Manager extends EventEmitter { } async unsubscribe (name) { - assert(this.subscriptions[name], `No subscriptions for ${name} were found.`) - this.subscriptions[name].stopping = true + const subscription = this.subscriptions[name] + + assert(subscription, `No subscriptions for ${name} were found.`) - this.subscriptions[name].workers.forEach(worker => worker.stop()) + subscription.stopping = true - // todo: we need to wait until each worker is done before killing the map key - // delete this.subscriptions[name] + subscription.workers.forEach(worker => worker.stop()) + + setInterval(() => { + if(subscription.workers.every(w => w.stopped)) { + delete this.subscriptions[name] + } + }, 2000) + } async offComplete (name) { diff --git a/src/worker.js b/src/worker.js index ca64ba91..16f4199b 100644 --- a/src/worker.js +++ b/src/worker.js @@ -6,7 +6,7 @@ class Worker { } async start () { - while (!this.stopped) { + while (!this.stopping) { const started = Date.now() try { @@ -18,14 +18,16 @@ class Worker { const duration = Date.now() - started - if (duration < this.config.interval) { + if (!this.stopping && duration < this.config.interval) { await delay(this.config.interval - duration) } } + + this.stopped = true } stop () { - this.stopped = true + this.stopping = true } } diff --git a/test/archiveTest.js b/test/archiveTest.js index 37981de5..96d632b6 100644 --- a/test/archiveTest.js +++ b/test/archiveTest.js @@ -27,7 +27,7 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive a created job', async function () { @@ -45,7 +45,7 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive a created job - cascaded config', async function () { @@ -63,6 +63,6 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/testHelper.js b/test/testHelper.js index 6d88b799..049a3995 100644 --- a/test/testHelper.js +++ b/test/testHelper.js @@ -39,6 +39,8 @@ function getConfig (options = {}) { config.schema = config.schema || 'pgboss' + config.stopOptions = { graceful: false } + const result = { ...config } return Object.assign(result, options) From d5ee5a6f60830bf0e48ef63d2eb2439e8957c61f Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Fri, 30 Apr 2021 12:39:43 -0500 Subject: [PATCH 03/19] fix --- src/boss.js | 14 +++++++++++--- src/index.js | 10 ++-------- src/manager.js | 24 +++++++++++------------- src/worker.js | 15 +++++++++------ 4 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/boss.js b/src/boss.js index 52342c0f..16a1336c 100644 --- a/src/boss.js +++ b/src/boss.js @@ -121,9 +121,17 @@ class Boss extends EventEmitter { const started = Date.now() - await this.expire() - await this.archive() - await this.purge() + if (!this.stopped) { + await this.expire() + } + + if (!this.stopped) { + await this.archive() + } + + if (!this.stopped) { + await this.purge() + } const ended = Date.now() diff --git a/src/index.js b/src/index.js index 41a00edc..f02ba4a8 100644 --- a/src/index.js +++ b/src/index.js @@ -122,30 +122,24 @@ class PgBoss extends EventEmitter { let polling = false const shutdown = async () => { - try { await this.boss.stop() if (this.db.isOurs) { await this.db.close() } - - } catch(err) { - - if(polling) { + } catch (err) { + if (polling) { this.emit('error', err) } else { throw err } - } finally { - this.isStarted = false this.stoppingOn = null this.emit('stopped') } - } if (!graceful) { diff --git a/src/manager.js b/src/manager.js index 33bba9d8..91a6efdf 100644 --- a/src/manager.js +++ b/src/manager.js @@ -58,17 +58,16 @@ class Manager extends EventEmitter { } async stop (options = {}) { - const { not = null } = options let subs = Object.values(this.subscriptions) - if(not) { + if (not) { subs = subs.filter(i => i.name !== not) } for (const sub of subs) { - await this.unsubscribe(sub.name) + await this.unsubscribe(sub.name) } } @@ -83,16 +82,20 @@ class Manager extends EventEmitter { } getWipData () { - return Object.values(this.subscriptions) + const data = Object.values(this.subscriptions) .map(({ name, jobs }) => ({ name, count: jobs.size() })) .filter(i => i.count > 0) + + return data } emitWipThrottled () { debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) } - registerWorker (name, worker) { + registerWorker (worker) { + const { name } = worker + if (!this.subscriptions[name]) { this.subscriptions[name] = { name, @@ -155,10 +158,6 @@ class Manager extends EventEmitter { const fetch = () => this.fetch(name, batchSize || teamSize, { includeMetadata }) const onFetch = async (jobs) => { - if (!jobs) { - return - } - this.registerJobs(name, jobs) // Failing will fail all fetched jobs @@ -166,7 +165,7 @@ class Manager extends EventEmitter { return await Promise.all([callback(jobs)]).catch(err => this.watchFail(name, jobs.map(job => job.id), err)) } - await pMap(jobs, job => + return await pMap(jobs, job => callback(job) .then(result => this.watchComplete(name, job.id, result)) .catch(err => this.watchFail(name, job.id, err)) @@ -175,6 +174,7 @@ class Manager extends EventEmitter { } const onError = error => { + console.log(error) this.emit(events.error, { ...error, pgbossWorker: id, pgbossQueue: name }) } @@ -186,7 +186,6 @@ class Manager extends EventEmitter { } async unsubscribe (name) { - const subscription = this.subscriptions[name] assert(subscription, `No subscriptions for ${name} were found.`) @@ -196,11 +195,10 @@ class Manager extends EventEmitter { subscription.workers.forEach(worker => worker.stop()) setInterval(() => { - if(subscription.workers.every(w => w.stopped)) { + if (subscription.workers.every(w => w.stopped)) { delete this.subscriptions[name] } }, 2000) - } async offComplete (name) { diff --git a/src/worker.js b/src/worker.js index 16f4199b..73035ee4 100644 --- a/src/worker.js +++ b/src/worker.js @@ -2,7 +2,7 @@ const delay = require('delay') class Worker { constructor (config) { - this.config = config + Object.assign(this, config) } async start () { @@ -10,16 +10,19 @@ class Worker { const started = Date.now() try { - const jobs = await this.config.fetch() - await this.config.onFetch(jobs) + const jobs = await this.fetch() + + if (jobs) { + await this.onFetch(jobs) + } } catch (err) { - this.config.onError(err) + this.onError(err) } const duration = Date.now() - started - if (!this.stopping && duration < this.config.interval) { - await delay(this.config.interval - duration) + if (!this.stopping && duration < this.interval) { + await delay(this.interval - duration) } } From c60247e108acfc5d2799fc4259b5eb00bde18ac1 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Fri, 30 Apr 2021 17:32:37 -0500 Subject: [PATCH 04/19] updates to state --- src/boss.js | 6 +++ src/db.js | 4 +- src/index.js | 8 ++- src/manager.js | 138 ++++++++++++++++++++++--------------------------- src/plans.js | 19 +++++-- src/worker.js | 47 ++++++++++++++++- 6 files changed, 137 insertions(+), 85 deletions(-) diff --git a/src/boss.js b/src/boss.js index 16a1336c..76dd9328 100644 --- a/src/boss.js +++ b/src/boss.js @@ -170,6 +170,12 @@ class Boss extends EventEmitter { async stop () { if (!this.stopped) { + await this.manager.unsubscribe(queues.MAINTENANCE) + + if (this.monitorStates) { + await this.manager.unsubscribe(queues.MONITOR_STATES) + } + if (this.metaMonitorInterval) { clearInterval(this.metaMonitorInterval) } diff --git a/src/db.js b/src/db.js index 80e0790e..7094092e 100644 --- a/src/db.js +++ b/src/db.js @@ -24,7 +24,9 @@ class Db extends EventEmitter { } async executeSql (text, values) { - return this.pool.query(text, values) + if (this.opened) { + return this.pool.query(text, values) + } } } diff --git a/src/index.js b/src/index.js index f02ba4a8..5b5463b7 100644 --- a/src/index.js +++ b/src/index.js @@ -8,6 +8,10 @@ const Boss = require('./boss') const Db = require('./db') const delay = require('delay') +const events = { + error: 'error', + stopped: 'stopped' +} class PgBoss extends EventEmitter { static getConstructionPlans (schema) { return Contractor.constructionPlans(schema) @@ -130,7 +134,7 @@ class PgBoss extends EventEmitter { } } catch (err) { if (polling) { - this.emit('error', err) + this.emit(events.error, err) } else { throw err } @@ -138,7 +142,7 @@ class PgBoss extends EventEmitter { this.isStarted = false this.stoppingOn = null - this.emit('stopped') + this.emit(events.stopped) } } diff --git a/src/manager.js b/src/manager.js index 91a6efdf..017139a6 100644 --- a/src/manager.js +++ b/src/manager.js @@ -26,7 +26,7 @@ class Manager extends EventEmitter { this.db = db this.events = events - this.subscriptions = {} + this.subscriptions = new Map() this.nextJobCommand = plans.fetchNextJob(config.schema) this.insertJobCommand = plans.insertJob(config.schema) @@ -60,13 +60,11 @@ class Manager extends EventEmitter { async stop (options = {}) { const { not = null } = options - let subs = Object.values(this.subscriptions) - - if (not) { - subs = subs.filter(i => i.name !== not) - } + for (const sub of this.subscriptions.values()) { + if (not && not === sub.name) { + continue + } - for (const sub of subs) { await this.unsubscribe(sub.name) } } @@ -82,8 +80,32 @@ class Manager extends EventEmitter { } getWipData () { - const data = Object.values(this.subscriptions) - .map(({ name, jobs }) => ({ name, count: jobs.size() })) + const data = Array.from(this.subscriptions.values()) + .map(({ + id, + name, + options, + state, + jobs, + createdOn, + lastFetchedOn, + lastJobStartedOn, + lastJobEndedOn, + lastError, + lastErrorOn + }) => ({ + id, + name, + options, + state, + count: jobs.length, + createdOn, + lastFetchedOn, + lastJobStartedOn, + lastJobEndedOn, + lastError, + lastErrorOn + })) .filter(i => i.count > 0) return data @@ -93,57 +115,6 @@ class Manager extends EventEmitter { debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) } - registerWorker (worker) { - const { name } = worker - - if (!this.subscriptions[name]) { - this.subscriptions[name] = { - name, - workers: [], - jobs: new Set() - } - } - - this.subscriptions[name].workers.push(worker) - } - - registerJobs (name, value) { - value = Array.isArray(value) ? value : [value] - - for (const job of value) { - this.subscriptions[name].jobs.add(job.id) - } - - this.emitWipThrottled() - } - - deregisterJobs (name, value) { - value = Array.isArray(value) ? value : [value] - - for (const jobId of value) { - this.subscriptions[name].jobs.delete(jobId) - } - - this.emitWipThrottled() - } - - async watchFinish (name, value, cb) { - try { - await cb() - this.deregisterJobs(name, value) - } catch (err) { - this.emit(events.error, err) - } - } - - async watchFail (name, value, data) { - await this.watchFinish(name, value, () => this.fail(value, data)) - } - - async watchComplete (name, value, data) { - await this.watchFinish(name, value, () => this.complete(value, data)) - } - async watch (name, options, callback) { const { newJobCheckInterval: interval = this.config.newJobCheckInterval, @@ -158,45 +129,60 @@ class Manager extends EventEmitter { const fetch = () => this.fetch(name, batchSize || teamSize, { includeMetadata }) const onFetch = async (jobs) => { - this.registerJobs(name, jobs) - // Failing will fail all fetched jobs if (batchSize) { - return await Promise.all([callback(jobs)]).catch(err => this.watchFail(name, jobs.map(job => job.id), err)) + return await Promise.all([callback(jobs)]).catch(err => this.fail(jobs.map(job => job.id), err)) } return await pMap(jobs, job => callback(job) - .then(result => this.watchComplete(name, job.id, result)) - .catch(err => this.watchFail(name, job.id, err)) + .then(result => this.complete(job.id, result)) + .catch(err => this.fail(job.id, err)) , { concurrency: teamConcurrency } ).catch(() => {}) // allow promises & non-promises to live together in harmony } const onError = error => { - console.log(error) - this.emit(events.error, { ...error, pgbossWorker: id, pgbossQueue: name }) + console.log(error) // todo: remove + this.emit(events.error, { ...error, queue: name, worker: id }) } - const worker = new Worker({ id, name, fetch, onFetch, onError, interval }) + const worker = new Worker({ id, name, options, interval, fetch, onFetch, onError }) - this.registerWorker(worker) + this.subscriptions.set(worker.id, worker) worker.start() + + return id } - async unsubscribe (name) { - const subscription = this.subscriptions[name] + async unsubscribe (value) { + assert(value, 'Missing required argument') - assert(subscription, `No subscriptions for ${name} were found.`) + const query = (typeof value === 'string') + ? { type: 'name', value, filter: i => i.name === value } + : (typeof value === 'object' && value.worker) + ? { type: 'worker', value: value.worker, filter: i => i.id === value.worker } + : null - subscription.stopping = true + assert(query, 'Invalid argument. Expected string or object: { worker: id }') - subscription.workers.forEach(worker => worker.stop()) + const workers = Array.from(this.subscriptions.values()) + .filter(i => query.filter(i) && !i.stopping && !i.stopped) + + if (workers.length === 0) { + return + } + + for (const worker of workers) { + worker.stop() + } setInterval(() => { - if (subscription.workers.every(w => w.stopped)) { - delete this.subscriptions[name] + if (workers.every(w => w.stopped)) { + for (const worker of workers) { + this.subscriptions.delete(worker.id) + } } }, 2000) } diff --git a/src/plans.js b/src/plans.js index cd4c2bc3..b59af51d 100644 --- a/src/plans.js +++ b/src/plans.js @@ -76,6 +76,7 @@ function create (schema, version) { addArchivedOnToArchive(schema), addArchivedOnIndexToArchive(schema), createIndexJobName(schema), + createIndexJobFetch(schema), createIndexSingletonOn(schema), createIndexSingletonKeyOn(schema), createIndexSingletonKey(schema), @@ -138,7 +139,8 @@ function createJobTable (schema) { createdOn timestamp with time zone not null default now(), completedOn timestamp with time zone, keepUntil timestamp with time zone NOT NULL default now() + interval '30 days', - on_complete boolean not null default true + on_complete boolean not null default true, + output jsonb ) ` } @@ -232,6 +234,12 @@ function createIndexJobName (schema) { ` } +function createIndexJobFetch (schema) { + return ` + CREATE INDEX job_fetch ON ${schema}.job (state, name text_pattern_ops, startAfter) + ` +} + function createScheduleTable (schema) { return ` CREATE TABLE ${schema}.schedule ( @@ -353,7 +361,8 @@ function completeJobs (schema) { WITH results AS ( UPDATE ${schema}.job SET completedOn = now(), - state = '${states.completed}' + state = '${states.completed}', + output = $2::jsonb WHERE id IN (SELECT UNNEST($1::uuid[])) AND state = '${states.active}' RETURNING * @@ -381,7 +390,8 @@ function failJobs (schema) { ELSE '${states.failed}'::${schema}.job_state END, completedOn = ${retryCompletedOnCase}, - startAfter = ${retryStartAfterCase} + startAfter = ${retryStartAfterCase}, + output = $2::jsonb WHERE id IN (SELECT UNNEST($1::uuid[])) AND state < '${states.completed}' RETURNING * @@ -409,7 +419,8 @@ function expire (schema) { ELSE '${states.expired}'::${schema}.job_state END, completedOn = ${retryCompletedOnCase}, - startAfter = ${retryStartAfterCase} + startAfter = ${retryStartAfterCase}, + output = $2::jsonb WHERE state = '${states.active}' AND (startedOn + expireIn) < now() RETURNING * diff --git a/src/worker.js b/src/worker.js index 73035ee4..ec9e03ea 100644 --- a/src/worker.js +++ b/src/worker.js @@ -1,21 +1,61 @@ const delay = require('delay') +const WORKER_STATES = { + created: 'created', + active: 'active', + stopping: 'stopping', + stopped: 'stopped' +} + class Worker { - constructor (config) { - Object.assign(this, config) + constructor ({ id, name, options, interval, fetch, onFetch, onError }) { + this.id = id + this.name = name + this.options = options + this.fetch = fetch + this.onFetch = onFetch + this.onError = onError + this.interval = interval + this.jobs = [] + this.createdOn = Date.now() + this.lastFetchedOn = null + this.lastJobStartedOn = null + this.lastJobEndedOn = null + this.lastError = null + this.lastErrorOn = null + this.state = WORKER_STATES.created + this.stopping = false + this.stopped = false } async start () { + this.state = WORKER_STATES.active + while (!this.stopping) { const started = Date.now() try { const jobs = await this.fetch() + this.lastFetchedOn = Date.now() + if (jobs) { + this.jobs = jobs + + this.lastJobStartedOn = this.lastFetchedOn + await this.onFetch(jobs) + + this.lastJobEndedOn = Date.now() + + this.jobs = [] } } catch (err) { + this.lastErrorOn = Date.now() + this.lastError = err + + err.message = `${err.message} (Queue: ${this.name}, Worker: ${this.id})` + this.onError(err) } @@ -26,11 +66,14 @@ class Worker { } } + this.stopping = false this.stopped = true + this.state = WORKER_STATES.stopped } stop () { this.stopping = true + this.state = WORKER_STATES.stopping } } From ea19450bca30b3939d5d1a777a614ec4c582a5e3 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Fri, 30 Apr 2021 17:32:55 -0500 Subject: [PATCH 05/19] ungraceful stops in test suite --- test/backgroundErrorTest.js | 13 ++++++++----- test/cancelTest.js | 8 ++++---- test/completeTest.js | 24 ++++++++++++------------ test/configTest.js | 4 ++-- test/databaseTest.js | 4 ++-- test/delayTest.js | 8 ++++---- test/deleteQueueTest.js | 6 +++--- test/deleteTest.js | 2 +- test/errorTest.js | 2 +- test/expireTest.js | 6 +++--- test/failureTest.js | 18 +++++++++--------- test/fetchTest.js | 10 +++++----- test/maintenanceTest.js | 2 +- test/managerTest.js | 2 +- test/migrationTest.js | 4 ++-- test/monitoringTest.js | 2 +- test/multiMasterTest.js | 4 ++-- test/opsTest.js | 10 +++++----- test/priorityTest.js | 4 ++-- test/publishTest.js | 14 +++++++------- test/retryTest.js | 12 ++++++------ test/scheduleTest.js | 20 ++++++++++---------- test/singletonTest.js | 10 +++++----- test/speedTest.js | 2 +- test/subscribeTest.js | 30 +++++++++++++++--------------- test/throttleTest.js | 12 ++++++------ test/wildcardTest.js | 4 ++-- 27 files changed, 120 insertions(+), 117 deletions(-) diff --git a/test/backgroundErrorTest.js b/test/backgroundErrorTest.js index 5093eeb1..96cb45dc 100644 --- a/test/backgroundErrorTest.js +++ b/test/backgroundErrorTest.js @@ -1,7 +1,7 @@ const PgBoss = require('../') - +const delay = require('delay') describe('background processing error handling', function () { - this.retries(1) + // this.retries(1) it('maintenance error handling works', function (done) { const defaults = { @@ -15,7 +15,8 @@ describe('background processing error handling', function () { boss.on('error', async () => { boss.removeAllListeners() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) + await delay(2000) done() }) @@ -34,7 +35,8 @@ describe('background processing error handling', function () { boss.on('error', async () => { boss.removeAllListeners() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) + await delay(2000) done() }) @@ -47,7 +49,8 @@ describe('background processing error handling', function () { boss.on('error', async () => { boss.removeAllListeners() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) + await delay(2000) done() }) diff --git a/test/cancelTest.js b/test/cancelTest.js index 38ef086a..3c2034c7 100644 --- a/test/cancelTest.js +++ b/test/cancelTest.js @@ -11,7 +11,7 @@ describe('cancel', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -27,7 +27,7 @@ describe('cancel', function () { assert(job && job.state === 'cancelled') - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not cancel a completed job', async function () { @@ -47,7 +47,7 @@ describe('cancel', function () { assert.strictEqual(response.updated, 0) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should cancel a batch of jobs', async function () { @@ -62,6 +62,6 @@ describe('cancel', function () { await boss.cancel(jobs) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/completeTest.js b/test/completeTest.js index a11d2c4c..2d77e1da 100644 --- a/test/completeTest.js +++ b/test/completeTest.js @@ -13,7 +13,7 @@ describe('complete', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -43,7 +43,7 @@ describe('complete', function () { assert.strictEqual(batchSize, completed.length) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('onComplete should have the payload from complete() in the response object', function (finished) { @@ -67,7 +67,7 @@ describe('complete', function () { assert.strictEqual(job.data.response.message, responsePayload.message) assert.strictEqual(job.data.response.arg2, responsePayload.arg2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }) @@ -90,7 +90,7 @@ describe('complete', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual(job.data.request.data.foo, requestPayload.foo) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }) @@ -117,7 +117,7 @@ describe('complete', function () { assert.strictEqual(job.data.response.message, responsePayload.message) assert.strictEqual(job.data.response.code, responsePayload.code) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }) @@ -141,7 +141,7 @@ describe('complete', function () { boss.onComplete(jobName, async job => { assert.strictEqual(job.data.response.arg1, responsePayload.arg1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }) @@ -177,7 +177,7 @@ describe('complete', function () { assert.strictEqual(receivedCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch a completed job', async function () { @@ -191,7 +191,7 @@ describe('complete', function () { assert.strictEqual(job.data.request.id, jobId) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create an extra state job after completion', async function () { @@ -213,7 +213,7 @@ describe('complete', function () { assert.strictEqual(stateJobCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create a completion job if opted out during publish', async function () { @@ -233,7 +233,7 @@ describe('complete', function () { assert.strictEqual(job, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create a completion job if opted out during constructor', async function () { @@ -253,7 +253,7 @@ describe('complete', function () { assert.strictEqual(job, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should create completion job if overriding the default from constructor', async function () { @@ -273,6 +273,6 @@ describe('complete', function () { assert.strictEqual(job.data.request.id, jobId) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/configTest.js b/test/configTest.js index 02bf17d8..118b9b72 100644 --- a/test/configTest.js +++ b/test/configTest.js @@ -12,7 +12,7 @@ describe('config', function () { const boss = new PgBoss(config) await boss.start() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) await helper.dropSchema(config.schema) }) @@ -32,7 +32,7 @@ describe('config', function () { const boss = new PgBoss({ connectionString, schema: this.test.bossConfig.schema }) await boss.start() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not allow calling job instance functions if not started', async function () { diff --git a/test/databaseTest.js b/test/databaseTest.js index f23f98f9..8c220dcb 100644 --- a/test/databaseTest.js +++ b/test/databaseTest.js @@ -12,7 +12,7 @@ describe('database', function () { await boss.start() assert(false) } catch (err) { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -59,7 +59,7 @@ describe('database', function () { const newConnections = connectionCount - prevConnectionCount - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) return newConnections diff --git a/test/delayTest.js b/test/delayTest.js index 89d251b7..4c111379 100644 --- a/test/delayTest.js +++ b/test/delayTest.js @@ -25,7 +25,7 @@ describe('delayed jobs', function () { assert(delaySeconds >= elapsedSeconds) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) resolve() }) @@ -54,7 +54,7 @@ describe('delayed jobs', function () { assert(job2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should wait until after a date object', async function () { @@ -78,7 +78,7 @@ describe('delayed jobs', function () { assert(job2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should work with publishAfter() and a date object', async function () { @@ -102,6 +102,6 @@ describe('delayed jobs', function () { assert(job2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/deleteQueueTest.js b/test/deleteQueueTest.js index 215c89ba..fba944ef 100644 --- a/test/deleteQueueTest.js +++ b/test/deleteQueueTest.js @@ -33,7 +33,7 @@ describe('deleteQueue', function () { assert.strictEqual(0, q2Count3) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should clear all queues', async function () { @@ -60,7 +60,7 @@ describe('deleteQueue', function () { assert.strictEqual(0, q1Count2) assert.strictEqual(0, q2Count2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('clearStorage() should empty both job storage tables', async function () { @@ -103,6 +103,6 @@ describe('deleteQueue', function () { assert(postJobCount === 0) assert(postArchiveCount === 0) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/deleteTest.js b/test/deleteTest.js index bebf9fd8..8c8815f7 100644 --- a/test/deleteTest.js +++ b/test/deleteTest.js @@ -26,6 +26,6 @@ describe('delete', async function () { assert.strictEqual(archivedJob, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/errorTest.js b/test/errorTest.js index e6d487ec..feba9d35 100644 --- a/test/errorTest.js +++ b/test/errorTest.js @@ -22,7 +22,7 @@ describe('error', function () { throw new Error('test - nothing to see here') } else { await job.done() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() } }) diff --git a/test/expireTest.js b/test/expireTest.js index 7f3fcf3f..1abdb3b6 100644 --- a/test/expireTest.js +++ b/test/expireTest.js @@ -22,7 +22,7 @@ describe('expire', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('expired', job.data.state) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should expire a job - cascaded config', async function () { @@ -42,7 +42,7 @@ describe('expire', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('expired', job.data.state) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should warn with an old expireIn option only once', async function () { @@ -68,6 +68,6 @@ describe('expire', function () { assert.strictEqual(warningCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/failureTest.js b/test/failureTest.js index e6a7d203..a994618c 100644 --- a/test/failureTest.js +++ b/test/failureTest.js @@ -12,7 +12,7 @@ describe('failure', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -26,7 +26,7 @@ describe('failure', function () { await boss.fail(job.id) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should subscribe to a job failure', async function () { @@ -44,7 +44,7 @@ describe('failure', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('failed', job.data.state) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) resolve() }).catch(reject) }) @@ -64,7 +64,7 @@ describe('failure', function () { const jobs = await boss.fetch(queue, 3) await boss.fail(jobs.map(job => job.id)) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept a payload', async function () { @@ -81,7 +81,7 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.someReason, failPayload.someReason) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('subscribe failure via done() should pass error payload to failed job', function (finished) { @@ -109,7 +109,7 @@ describe('failure', function () { assert.strictEqual(failedJob.data.state, 'failed') assert.strictEqual(failedJob.data.response.message, errorMessage) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() } @@ -132,7 +132,7 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.value, failPayload) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('subscribe failure via Promise reject() should pass object payload', async function () { @@ -153,7 +153,7 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.something, something) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('failure with Error object should get stored in the failure job', async function () { @@ -171,6 +171,6 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert(job.data.response.message.includes(message)) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/fetchTest.js b/test/fetchTest.js index 47b3420b..62d5dd25 100644 --- a/test/fetchTest.js +++ b/test/fetchTest.js @@ -11,7 +11,7 @@ describe('fetch', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -24,7 +24,7 @@ describe('fetch', function () { assert(jobName === job.name) // Metadata should only be included when specifically requested assert(job.startedon === undefined) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should get a batch of jobs as an array', async function () { @@ -46,7 +46,7 @@ describe('fetch', function () { // Metadata should only be included when specifically requested assert(jobs[0].startedon === undefined) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch all metadata for a single job when requested', async function () { @@ -70,7 +70,7 @@ describe('fetch', function () { assert(job.createdon !== undefined) assert(job.completedon === null) assert(job.keepuntil !== undefined) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch all metadata for a batch of jobs when requested', async function () { @@ -106,6 +106,6 @@ describe('fetch', function () { assert(job.completedon === null) assert(job.keepuntil !== undefined) }) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/maintenanceTest.js b/test/maintenanceTest.js index a963f929..b9444dd7 100644 --- a/test/maintenanceTest.js +++ b/test/maintenanceTest.js @@ -27,6 +27,6 @@ describe('maintenance', async function () { const count = await countJobs() assert(count > 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/managerTest.js b/test/managerTest.js index fcbc9b67..187206f7 100644 --- a/test/managerTest.js +++ b/test/managerTest.js @@ -14,7 +14,7 @@ describe('manager', function () { await boss.start() assert(false) } catch (error) { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) }) diff --git a/test/migrationTest.js b/test/migrationTest.js index 3d3f4e90..ae5bb450 100644 --- a/test/migrationTest.js +++ b/test/migrationTest.js @@ -42,7 +42,7 @@ describe('migration', function () { assert.strictEqual(version, currentSchemaVersion) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should migrate through 2 versions back and forth', async function () { @@ -108,7 +108,7 @@ describe('migration', function () { assert.strictEqual(version, currentSchemaVersion) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('migrating to non-existent version fails gracefully', async function () { diff --git a/test/monitoringTest.js b/test/monitoringTest.js index 116be0a5..4855a877 100644 --- a/test/monitoringTest.js +++ b/test/monitoringTest.js @@ -51,7 +51,7 @@ describe('monitoring', function () { assert.strictEqual(states4.queues[queue].active, states.queues[queue].active, 'active count from monitor-states doesn\'t match') assert.strictEqual(states4.queues[queue].completed, states.queues[queue].completed, 'completed count from monitor-states doesn\'t match') - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) resolve() }) diff --git a/test/multiMasterTest.js b/test/multiMasterTest.js index 932e33c0..1c34c1af 100644 --- a/test/multiMasterTest.js +++ b/test/multiMasterTest.js @@ -88,7 +88,7 @@ describe('multi-master', function () { assert.strictEqual(beforeCount, jobCount) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) boss = new PgBoss(this.test.bossConfig) @@ -100,6 +100,6 @@ describe('multi-master', function () { assert.strictEqual(completedCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/opsTest.js b/test/opsTest.js index 0ab8b2e9..f9db0d49 100644 --- a/test/opsTest.js +++ b/test/opsTest.js @@ -7,26 +7,26 @@ describe('ops', function () { it('should start back up after stopping', async function () { const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) await boss.start() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should expire manually', async function () { const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.expire() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive manually', async function () { const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.archive() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should purge the archive manually', async function () { const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.purge() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/priorityTest.js b/test/priorityTest.js index 871c45cd..cde6b9ab 100644 --- a/test/priorityTest.js +++ b/test/priorityTest.js @@ -15,7 +15,7 @@ describe('priority', function () { assert.strictEqual(job.id, high) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should process several jobs in descending priority order', async function () { @@ -35,6 +35,6 @@ describe('priority', function () { assert.strictEqual(job2.id, medium) assert.strictEqual(job3.id, low) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/publishTest.js b/test/publishTest.js index eff4ac6b..fa9cd447 100644 --- a/test/publishTest.js +++ b/test/publishTest.js @@ -11,7 +11,7 @@ describe('publish', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -24,7 +24,7 @@ describe('publish', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -37,7 +37,7 @@ describe('publish', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -45,14 +45,14 @@ describe('publish', function () { const boss = await helper.start(this.test.bossConfig) const queue = 'publishNameOnly' await boss.publish(queue) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object argument with only name', async function () { const boss = await helper.start(this.test.bossConfig) const queue = 'publishqueueOnly' await boss.publish({ name: queue }) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object with name and data only', async function () { @@ -65,7 +65,7 @@ describe('publish', function () { const job = await boss.fetch(queue) assert.strictEqual(message, job.data.message) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object with name and options only', async function () { @@ -79,6 +79,6 @@ describe('publish', function () { assert.strictEqual(job.data, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/retryTest.js b/test/retryTest.js index 305331a2..704011ec 100644 --- a/test/retryTest.js +++ b/test/retryTest.js @@ -20,7 +20,7 @@ describe('retries', function () { assert.strictEqual(try1.id, jobId) assert.strictEqual(try2.id, jobId) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry a job that failed', async function () { @@ -37,7 +37,7 @@ describe('retries', function () { assert.strictEqual(job.id, jobId) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry a job that failed with cascaded config', async function () { @@ -54,7 +54,7 @@ describe('retries', function () { assert.strictEqual(job.id, jobId) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry with a fixed delay', async function () { @@ -76,7 +76,7 @@ describe('retries', function () { assert(job2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry with a exponential backoff', async function () { @@ -93,7 +93,7 @@ describe('retries', function () { assert(subscribeCount < retryLimit) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should set the default retry limit to 1 if missing', async function () { @@ -114,6 +114,6 @@ describe('retries', function () { assert(job2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/scheduleTest.js b/test/scheduleTest.js index aa6e8deb..68697c37 100644 --- a/test/scheduleTest.js +++ b/test/scheduleTest.js @@ -21,7 +21,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept a custom clock monitoring interval in seconds', async function () { @@ -42,7 +42,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('cron monitoring should restart cron if paused', async function () { @@ -68,7 +68,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should publish job based on every minute expression after a restart', async function () { @@ -78,7 +78,7 @@ describe('schedule', function () { await boss.schedule(queue, '* * * * *') - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) boss = await helper.start(this.test.bossConfig) @@ -88,7 +88,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should remove previously scheduled job', async function () { @@ -100,7 +100,7 @@ describe('schedule', function () { await boss.unschedule(queue) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) const db = await helper.getDb() await db.executeSql(plans.clearStorage(this.test.bossConfig.schema)) @@ -113,7 +113,7 @@ describe('schedule', function () { assert(job === null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should publish job based on current minute in UTC', async function () { @@ -140,7 +140,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should publish job based on current minute in a specified time zone', async function () { @@ -172,7 +172,7 @@ describe('schedule', function () { assert(job) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should force a clock skew warning', async function () { @@ -194,6 +194,6 @@ describe('schedule', function () { assert.strictEqual(warningCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/singletonTest.js b/test/singletonTest.js index f5735062..91a84565 100644 --- a/test/singletonTest.js +++ b/test/singletonTest.js @@ -15,7 +15,7 @@ describe('singleton', function () { assert.strictEqual(jobId2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should not allow more than 1 complete job with the same key with an interval', async function () { @@ -33,7 +33,7 @@ describe('singleton', function () { assert.strictEqual(jobId, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should allow more than 1 pending job at the same time with different keys', async function () { @@ -48,7 +48,7 @@ describe('singleton', function () { assert(jobId2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('publishOnce() should work', async function () { @@ -64,7 +64,7 @@ describe('singleton', function () { assert.strictEqual(jobId2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('publishOnce() without a key should also work', async function () { @@ -79,6 +79,6 @@ describe('singleton', function () { assert.strictEqual(jobId2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/speedTest.js b/test/speedTest.js index 21036f0d..983dd5f6 100644 --- a/test/speedTest.js +++ b/test/speedTest.js @@ -18,7 +18,7 @@ describe('speed', function () { await pMap(jobs, job => boss.publish(job.name, job.data)) }) - afterEach(async function () { await boss.stop() }) + afterEach(async function () { await boss.stop(this.test.bossConfig.stopOptions) }) it(testTitle, async function () { this.timeout(expectedSeconds * 1000) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index f8c4ab7b..fd7d5e87 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -12,7 +12,7 @@ describe('subscribe', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -25,7 +25,7 @@ describe('subscribe', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -38,7 +38,7 @@ describe('subscribe', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -51,7 +51,7 @@ describe('subscribe', function () { } catch (err) { assert(err) } finally { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) } }) @@ -74,7 +74,7 @@ describe('subscribe', function () { assert(subscribeCount <= timeout / 1000 / newJobCheckIntervalSeconds) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should unsubscribe a subscription', async function () { @@ -96,7 +96,7 @@ describe('subscribe', function () { assert.strictEqual(receivedCount, 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should handle a batch of jobs via teamSize', async function () { @@ -119,7 +119,7 @@ describe('subscribe', function () { // test would time out if it had to wait for 4 fetch intervals if (subscribeCount === teamSize) { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) resolve() } }).catch(reject) @@ -150,7 +150,7 @@ describe('subscribe', function () { subscribeCount++ if (subscribeCount === teamSize) { - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() } @@ -177,7 +177,7 @@ describe('subscribe', function () { boss.subscribe(queue, { batchSize }, async jobs => { assert.strictEqual(jobs.length, batchSize) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }).catch(finished) } @@ -204,7 +204,7 @@ describe('subscribe', function () { assert(subscribeCount < batchSize) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should have a done callback for single job subscriptions', function (finished) { @@ -220,7 +220,7 @@ describe('subscribe', function () { boss.subscribe(queue, async job => { await job.done() - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }) } @@ -248,7 +248,7 @@ describe('subscribe', function () { assert.strictEqual(job.data.state, 'completed') assert.strictEqual(job.data.response.value, result) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() } @@ -276,7 +276,7 @@ describe('subscribe', function () { assert.strictEqual(job.data.state, 'completed') assert.strictEqual(job.data.response.something, something) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() } @@ -290,7 +290,7 @@ describe('subscribe', function () { await boss.subscribe(queue, () => {}) await boss.subscribe(queue, () => {}) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should honor the includeMetadata option', function (finished) { @@ -307,7 +307,7 @@ describe('subscribe', function () { boss.subscribe(queue, { includeMetadata: true }, async job => { assert(job.startedon !== undefined) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) finished() }).catch(finished) } diff --git a/test/throttleTest.js b/test/throttleTest.js index 3c925908..6db7dd2f 100644 --- a/test/throttleTest.js +++ b/test/throttleTest.js @@ -25,7 +25,7 @@ describe('throttle', function () { assert(subscribeCount <= 2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should process at most 1 job per second', async function () { @@ -51,7 +51,7 @@ describe('throttle', function () { assert(subscribeCount <= jobCount + 1) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should debounce', async function () { @@ -67,7 +67,7 @@ describe('throttle', function () { assert(jobId2) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should debounce via publishDebounced()', async function () { @@ -88,7 +88,7 @@ describe('throttle', function () { assert.strictEqual(jobId3, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should reject 2nd request in the same time slot', async function () { @@ -104,7 +104,7 @@ describe('throttle', function () { assert.strictEqual(jobId2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) it('should throttle via publishThrottled()', async function () { @@ -121,6 +121,6 @@ describe('throttle', function () { assert.strictEqual(jobId2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/wildcardTest.js b/test/wildcardTest.js index 0ebeb8d8..0c81dbcc 100644 --- a/test/wildcardTest.js +++ b/test/wildcardTest.js @@ -28,7 +28,7 @@ describe('wildcard', function () { boss.subscribe(`${baseName}_*`, { batchSize: 2 }, jobs => { assert.strictEqual(jobs.length, 2) - boss.stop().then(() => finished()) + boss.stop(this.test.bossConfig.stopOptions).then(() => finished()) }) } }) @@ -44,6 +44,6 @@ describe('wildcard', function () { const job2 = await boss.fetch(`${baseName}_*`) assert.strictEqual(job2, null) - await boss.stop() + await boss.stop(this.test.bossConfig.stopOptions) }) }) From b9ecad113a8ed1940a4abf3c463da3ed03aa2e15 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Sat, 1 May 2021 01:10:44 -0500 Subject: [PATCH 06/19] wip --- src/boss.js | 34 ++++--- src/manager.js | 21 +++- src/plans.js | 3 +- test/archiveTest.js | 15 +-- test/backgroundErrorTest.js | 16 +-- test/cancelTest.js | 16 +-- test/completeTest.js | 151 +++++++++++------------------ test/configTest.js | 9 +- test/databaseTest.js | 6 +- test/delayTest.js | 19 ++-- test/deleteQueueTest.js | 23 ++--- test/deleteTest.js | 4 +- test/errorTest.js | 24 ++--- test/expireTest.js | 16 ++- test/failureTest.js | 73 ++++++-------- test/fetchTest.js | 19 +--- test/global.js | 17 +++- test/maintenanceTest.js | 4 +- test/managerTest.js | 6 +- test/migrationTest.js | 10 +- test/monitoringTest.js | 4 +- test/multiMasterTest.js | 4 +- test/opsTest.js | 16 +-- test/priorityTest.js | 12 +-- test/publishTest.js | 25 ++--- test/retryTest.js | 33 +++---- test/scheduleTest.js | 52 ++++------ test/singletonTest.js | 27 ++---- test/speedTest.js | 2 +- test/subscribeTest.js | 188 ++++++++++++------------------------ test/testHelper.js | 8 +- test/throttleTest.js | 36 +++---- test/wildcardTest.js | 27 +++--- 33 files changed, 345 insertions(+), 575 deletions(-) diff --git a/src/boss.js b/src/boss.js index 76dd9328..39334963 100644 --- a/src/boss.js +++ b/src/boss.js @@ -121,17 +121,9 @@ class Boss extends EventEmitter { const started = Date.now() - if (!this.stopped) { - await this.expire() - } - - if (!this.stopped) { - await this.archive() - } - - if (!this.stopped) { - await this.purge() - } + await this.expire() + await this.archive() + await this.purge() const ended = Date.now() @@ -190,7 +182,7 @@ class Boss extends EventEmitter { Object.keys(stateCountDefault) .forEach(key => { stateCountDefault[key] = 0 }) - const counts = await this.db.executeSql(this.countStatesCommand) + const counts = await this.executeSql(this.countStatesCommand) const states = counts.rows.reduce((acc, item) => { if (item.name) { @@ -210,22 +202,26 @@ class Boss extends EventEmitter { } async expire () { - await this.db.executeSql(plans.locked(this.expireCommand)) + await this.executeSql(plans.locked(this.expireCommand)) } async archive () { - await this.db.executeSql(plans.locked(this.archiveCommand)) + await this.executeSql(plans.locked(this.archiveCommand)) } async purge () { - await this.db.executeSql(plans.locked(this.purgeCommand)) + await this.executeSql(plans.locked(this.purgeCommand)) } async setMaintenanceTime () { - await this.db.executeSql(this.setMaintenanceTimeCommand) + await this.executeSql(this.setMaintenanceTimeCommand) } async getMaintenanceTime () { + if (this.stopped) { + return + } + const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand) let { maintained_on: maintainedOn, seconds_ago: secondsAgo } = rows[0] @@ -238,6 +234,12 @@ class Boss extends EventEmitter { getQueueNames () { return queues } + + async executeSql (sql, params) { + if (!this.stopped) { + return await this.db.executeSql(sql, params) + } + } } module.exports = Boss diff --git a/src/manager.js b/src/manager.js index 017139a6..320db4ba 100644 --- a/src/manager.js +++ b/src/manager.js @@ -79,8 +79,20 @@ class Manager extends EventEmitter { return this.watch(COMPLETION_JOB_PREFIX + name, options, callback) } + addWorker (worker) { + this.subscriptions.set(worker.id, worker) + } + + removeWorker (worker) { + this.subscriptions.delete(worker.id) + } + + getWorkers () { + return Array.from(this.subscriptions.values()) + } + getWipData () { - const data = Array.from(this.subscriptions.values()) + const data = this.getWorkers() .map(({ id, name, @@ -149,7 +161,7 @@ class Manager extends EventEmitter { const worker = new Worker({ id, name, options, interval, fetch, onFetch, onError }) - this.subscriptions.set(worker.id, worker) + this.addWorker(worker) worker.start() @@ -167,8 +179,7 @@ class Manager extends EventEmitter { assert(query, 'Invalid argument. Expected string or object: { worker: id }') - const workers = Array.from(this.subscriptions.values()) - .filter(i => query.filter(i) && !i.stopping && !i.stopped) + const workers = this.getWorkers().filter(i => query.filter(i) && !i.stopping && !i.stopped) if (workers.length === 0) { return @@ -181,7 +192,7 @@ class Manager extends EventEmitter { setInterval(() => { if (workers.every(w => w.stopped)) { for (const worker of workers) { - this.subscriptions.delete(worker.id) + this.removeWorker(worker) } } }, 2000) diff --git a/src/plans.js b/src/plans.js index b59af51d..62286579 100644 --- a/src/plans.js +++ b/src/plans.js @@ -419,8 +419,7 @@ function expire (schema) { ELSE '${states.expired}'::${schema}.job_state END, completedOn = ${retryCompletedOnCase}, - startAfter = ${retryStartAfterCase}, - output = $2::jsonb + startAfter = ${retryStartAfterCase} WHERE state = '${states.active}' AND (startedOn + expireIn) < now() RETURNING * diff --git a/test/archiveTest.js b/test/archiveTest.js index 96d632b6..765e3d67 100644 --- a/test/archiveTest.js +++ b/test/archiveTest.js @@ -10,7 +10,8 @@ describe('archive', function () { it('should archive a completed job', async function () { const config = { ...this.test.bossConfig, ...defaults } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) + const queue = 'archive-completed' const jobId = await boss.publish(queue) @@ -20,19 +21,17 @@ describe('archive', function () { await boss.complete(jobId) - await delay(7000) + await delay(4000) const archivedJob = await helper.getArchivedJobById(config.schema, jobId) assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive a created job', async function () { const config = { ...this.test.bossConfig, ...defaults } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) const queue = 'archive-created' @@ -44,13 +43,11 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive a created job - cascaded config', async function () { const config = { ...this.test.bossConfig, ...defaults, retentionSeconds: 1 } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) const queue = 'archive-created-cascaded-config' @@ -62,7 +59,5 @@ describe('archive', function () { assert.strictEqual(jobId, archivedJob.id) assert.strictEqual(queue, archivedJob.name) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/backgroundErrorTest.js b/test/backgroundErrorTest.js index 96cb45dc..a1061c7c 100644 --- a/test/backgroundErrorTest.js +++ b/test/backgroundErrorTest.js @@ -1,8 +1,6 @@ const PgBoss = require('../') -const delay = require('delay') -describe('background processing error handling', function () { - // this.retries(1) +describe('background processing error handling', function () { it('maintenance error handling works', function (done) { const defaults = { monitorStateIntervalMinutes: 1, @@ -11,12 +9,10 @@ describe('background processing error handling', function () { } const config = { ...this.test.bossConfig, ...defaults } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) boss.on('error', async () => { boss.removeAllListeners() - await boss.stop(this.test.bossConfig.stopOptions) - await delay(2000) done() }) @@ -31,12 +27,10 @@ describe('background processing error handling', function () { } const config = { ...this.test.bossConfig, ...defaults } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) boss.on('error', async () => { boss.removeAllListeners() - await boss.stop(this.test.bossConfig.stopOptions) - await delay(2000) done() }) @@ -45,12 +39,10 @@ describe('background processing error handling', function () { it('clock monitoring error handling works', function (done) { const config = { ...this.test.bossConfig, __test__throw_clock_monitoring: true } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) boss.on('error', async () => { boss.removeAllListeners() - await boss.stop(this.test.bossConfig.stopOptions) - await delay(2000) done() }) diff --git a/test/cancelTest.js b/test/cancelTest.js index 3c2034c7..370acca5 100644 --- a/test/cancelTest.js +++ b/test/cancelTest.js @@ -3,21 +3,19 @@ const helper = require('./testHelper') describe('cancel', function () { it('should reject missing id argument', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.cancel() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should cancel a pending job', async function () { const config = this.test.bossConfig - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) const jobId = await boss.publish('will_cancel', null, { startAfter: 1 }) @@ -26,14 +24,12 @@ describe('cancel', function () { const job = await helper.getJobById(config.schema, jobId) assert(job && job.state === 'cancelled') - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not cancel a completed job', async function () { const config = this.test.bossConfig - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) const queue = 'will_not_cancel' @@ -46,14 +42,12 @@ describe('cancel', function () { const response = await boss.cancel(job.id) assert.strictEqual(response.updated, 0) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should cancel a batch of jobs', async function () { const queue = 'cancel-batch' - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) const jobs = await Promise.all([ boss.publish(queue), boss.publish(queue), @@ -61,7 +55,5 @@ describe('cancel', function () { ]) await boss.cancel(jobs) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/completeTest.js b/test/completeTest.js index 2d77e1da..502a512c 100644 --- a/test/completeTest.js +++ b/test/completeTest.js @@ -5,24 +5,22 @@ const PgBoss = require('../') describe('complete', function () { it('should reject missing id argument', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.complete() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should complete a batch of jobs', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'complete-batch' const batchSize = 3 - const boss = await helper.start(this.test.bossConfig) - await Promise.all([ boss.publish(queue), boss.publish(queue), @@ -42,122 +40,100 @@ describe('complete', function () { const completed = await boss.fetchCompleted(queue, batchSize) assert.strictEqual(batchSize, completed.length) - - await boss.stop(this.test.bossConfig.stopOptions) }) - it('onComplete should have the payload from complete() in the response object', function (finished) { - const config = this.test.bossConfig + it('onComplete should have the payload from complete() in the response object', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - test() + const jobName = 'part-of-something-important' + const responsePayload = { message: 'super-important-payload', arg2: '123' } - async function test () { - const jobName = 'part-of-something-important' - const responsePayload = { message: 'super-important-payload', arg2: '123' } - - const boss = await helper.start(config) - - await boss.publish(jobName) + await boss.publish(jobName) - const job = await boss.fetch(jobName) + const job = await boss.fetch(jobName) - await boss.complete(job.id, responsePayload) + await boss.complete(job.id, responsePayload) + return new Promise((resolve) => { boss.onComplete(jobName, async job => { assert.strictEqual(job.data.response.message, responsePayload.message) assert.strictEqual(job.data.response.arg2, responsePayload.arg2) - await boss.stop(this.test.bossConfig.stopOptions) - - finished() + resolve() }) - } + }) }) - it('onComplete should have the original payload in request object', function (finished) { - const config = this.test.bossConfig + it('onComplete should have the original payload in request object', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - test() + const queueName = 'onCompleteRequestTest' + const requestPayload = { foo: 'bar' } - async function test () { - const queueName = 'onCompleteRequestTest' - const requestPayload = { foo: 'bar' } + const jobId = await boss.publish(queueName, requestPayload) - const boss = await helper.start(config) - const jobId = await boss.publish(queueName, requestPayload) + const job = await boss.fetch(queueName) + await boss.complete(job.id) + return new Promise((resolve) => { boss.onComplete(queueName, async job => { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual(job.data.request.data.foo, requestPayload.foo) - await boss.stop(this.test.bossConfig.stopOptions) - finished() + resolve() }) - - const job = await boss.fetch(queueName) - await boss.complete(job.id) - } + }) }) - it('onComplete should have both request and response', function (finished) { - const config = this.test.bossConfig + it('onComplete should have both request and response', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - test() + const jobName = 'onCompleteFtw' + const requestPayload = { token: 'trivial' } + const responsePayload = { message: 'so verbose', code: '1234' } - async function test () { - const jobName = 'onCompleteFtw' - const requestPayload = { token: 'trivial' } - const responsePayload = { message: 'so verbose', code: '1234' } + const jobId = await boss.publish(jobName, requestPayload) + const job = await boss.fetch(jobName) - const boss = await helper.start(config) + await boss.complete(job.id, responsePayload) + return new Promise((resolve) => { boss.onComplete(jobName, async job => { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual(job.data.request.data.token, requestPayload.token) assert.strictEqual(job.data.response.message, responsePayload.message) assert.strictEqual(job.data.response.code, responsePayload.code) - await boss.stop(this.test.bossConfig.stopOptions) - finished() + resolve() }) - - const jobId = await boss.publish(jobName, requestPayload) - const job = await boss.fetch(jobName) - - await boss.complete(job.id, responsePayload) - } + }) }) - it('subscribe()\'s job.done() should allow sending completion payload', function (finished) { - const config = this.test.bossConfig + it('subscribe()\'s job.done() should allow sending completion payload', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - test() + const jobName = 'complete-from-subscribe' + const responsePayload = { arg1: '123' } - async function test () { - const jobName = 'complete-from-subscribe' - const responsePayload = { arg1: '123' } + await boss.publish(jobName) - const boss = await helper.start(config) + boss.subscribe(jobName, job => job.done(null, responsePayload)) + return new Promise((resolve) => { boss.onComplete(jobName, async job => { assert.strictEqual(job.data.response.arg1, responsePayload.arg1) - await boss.stop(this.test.bossConfig.stopOptions) - finished() + resolve() }) - - await boss.publish(jobName) - - boss.subscribe(jobName, job => job.done(null, responsePayload)) - } + }) }) it('should unsubscribe an onComplete subscription', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const jobName = 'offComplete' let receivedCount = 0 - const boss = await helper.start(this.test.bossConfig) - boss.onComplete(jobName, async job => { receivedCount++ await boss.offComplete(jobName) @@ -176,29 +152,26 @@ describe('complete', function () { await delay(2000) assert.strictEqual(receivedCount, 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch a completed job', async function () { - const queue = 'fetchCompleted' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'fetchCompleted' const jobId = await boss.publish(queue) await boss.fetch(queue) await boss.complete(jobId) const job = await boss.fetchCompleted(queue) assert.strictEqual(job.data.request.id, jobId) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create an extra state job after completion', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'noMoreExtraStateJobs' const config = this.test.bossConfig - const boss = await helper.start(config) const jobId = await boss.publish(queue) await boss.fetch(queue) @@ -212,16 +185,12 @@ describe('complete', function () { const stateJobCount = await helper.countJobs(config.schema, 'name = $1', [`${helper.completedJobPrefix}${queue}`]) assert.strictEqual(stateJobCount, 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create a completion job if opted out during publish', async function () { - const queue = 'onCompleteOptOut' - - const config = this.test.bossConfig + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(config) + const queue = 'onCompleteOptOut' const jobId = await boss.publish(queue, null, { onComplete: false }) @@ -232,16 +201,12 @@ describe('complete', function () { const job = await boss.fetchCompleted(queue) assert.strictEqual(job, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not create a completion job if opted out during constructor', async function () { - const queue = 'onCompleteOptOutGlobal' + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: false }) - const config = this.test.bossConfig - - const boss = await helper.start({ ...config, onComplete: false }) + const queue = 'onCompleteOptOutGlobal' const jobId = await boss.publish(queue) @@ -252,16 +217,12 @@ describe('complete', function () { const job = await boss.fetchCompleted(queue) assert.strictEqual(job, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should create completion job if overriding the default from constructor', async function () { - const queue = 'onCompleteOptInOverride' - - const config = this.test.bossConfig + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: false }) - const boss = await helper.start({ ...config, onComplete: false }) + const queue = 'onCompleteOptInOverride' const jobId = await boss.publish(queue, null, { onComplete: true }) @@ -272,7 +233,5 @@ describe('complete', function () { const job = await boss.fetchCompleted(queue) assert.strictEqual(job.data.request.id, jobId) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/configTest.js b/test/configTest.js index 118b9b72..0da056c1 100644 --- a/test/configTest.js +++ b/test/configTest.js @@ -5,16 +5,14 @@ const helper = require('./testHelper') describe('config', function () { it('should allow a 50 character custom schema name', async function () { const config = this.test.bossConfig + config.schema = 'thisisareallylongschemanamefortestingmaximumlength' assert.strictEqual(config.schema.length, 50) - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) await boss.start() - await boss.stop(this.test.bossConfig.stopOptions) - - await helper.dropSchema(config.schema) }) it('should not allow more than 50 characters in schema name', function () { @@ -29,10 +27,9 @@ describe('config', function () { it('should accept a connectionString property', async function () { const connectionString = helper.getConnectionString() - const boss = new PgBoss({ connectionString, schema: this.test.bossConfig.schema }) + const boss = this.test.boss = new PgBoss({ connectionString, schema: this.test.bossConfig.schema }) await boss.start() - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not allow calling job instance functions if not started', async function () { diff --git a/test/databaseTest.js b/test/databaseTest.js index 8c220dcb..75481ef3 100644 --- a/test/databaseTest.js +++ b/test/databaseTest.js @@ -12,7 +12,7 @@ describe('database', function () { await boss.start() assert(false) } catch (err) { - await boss.stop(this.test.bossConfig.stopOptions) + assert(true) } }) @@ -35,7 +35,7 @@ describe('database', function () { const listenerCount = 100 const poolSize = 5 - const boss = await helper.start({ ...this.test.bossConfig, max: poolSize }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, max: poolSize }) const newConnections = await poolSizeConnectionTest(boss, listenerCount) @@ -59,8 +59,6 @@ describe('database', function () { const newConnections = connectionCount - prevConnectionCount - await boss.stop(this.test.bossConfig.stopOptions) - return newConnections async function countConnections (db) { diff --git a/test/delayTest.js b/test/delayTest.js index 4c111379..df1a0721 100644 --- a/test/delayTest.js +++ b/test/delayTest.js @@ -4,11 +4,11 @@ const delay = require('delay') describe('delayed jobs', function () { it('should wait until after an int (in seconds)', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const delaySeconds = 2 const queue = 'wait' - const boss = await helper.start(this.test.bossConfig) - const data = { message: 'hold your horses', submitted: Date.now() } const options = { startAfter: delaySeconds } @@ -25,14 +25,14 @@ describe('delayed jobs', function () { assert(delaySeconds >= elapsedSeconds) - await boss.stop(this.test.bossConfig.stopOptions) - resolve() }) }) }) it('should wait until after a date time string', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'delay-date-string' const date = new Date() @@ -41,7 +41,6 @@ describe('delayed jobs', function () { const startAfter = date.toISOString() - const boss = await helper.start(this.test.bossConfig) await boss.publish(queue, null, { startAfter }) const job = await boss.fetch(queue) @@ -53,11 +52,10 @@ describe('delayed jobs', function () { const job2 = await boss.fetch(queue) assert(job2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should wait until after a date object', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'delay-date-object' const date = new Date() @@ -65,7 +63,6 @@ describe('delayed jobs', function () { const startAfter = date - const boss = await helper.start(this.test.bossConfig) await boss.publish(queue, null, { startAfter }) const job = await boss.fetch(queue) @@ -77,11 +74,10 @@ describe('delayed jobs', function () { const job2 = await boss.fetch(queue) assert(job2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should work with publishAfter() and a date object', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'publishAfter-date-object' const date = new Date() @@ -89,7 +85,6 @@ describe('delayed jobs', function () { const startAfter = date - const boss = await helper.start(this.test.bossConfig) await boss.publishAfter(queue, { something: 1 }, { retryLimit: 0 }, startAfter) const job = await boss.fetch(queue) @@ -101,7 +96,5 @@ describe('delayed jobs', function () { const job2 = await boss.fetch(queue) assert(job2) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/deleteQueueTest.js b/test/deleteQueueTest.js index fba944ef..9116b24c 100644 --- a/test/deleteQueueTest.js +++ b/test/deleteQueueTest.js @@ -4,11 +4,10 @@ const delay = require('delay') describe('deleteQueue', function () { it('should clear a specific queue', async function () { - const queue1 = 'delete-named-queue-1' - const queue2 = 'delete-named-queue-2' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const config = this.test.bossConfig - const boss = await helper.start(config) + const queue2 = 'delete-named-queue-2' + const queue1 = 'delete-named-queue-1' await boss.publish(queue1) await boss.publish(queue2) @@ -32,17 +31,14 @@ describe('deleteQueue', function () { const q2Count3 = await boss.getQueueSize(queue2) assert.strictEqual(0, q2Count3) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should clear all queues', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue1 = 'delete-named-queue-11' const queue2 = 'delete-named-queue-22' - const config = this.test.bossConfig - const boss = await helper.start(config) - await boss.publish(queue1) await boss.publish(queue2) @@ -59,8 +55,6 @@ describe('deleteQueue', function () { assert.strictEqual(0, q1Count2) assert.strictEqual(0, q2Count2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('clearStorage() should empty both job storage tables', async function () { @@ -68,9 +62,8 @@ describe('deleteQueue', function () { archiveCompletedAfterSeconds: 1, maintenanceIntervalSeconds: 1 } + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) - const config = { ...this.test.bossConfig, ...defaults } - const boss = await helper.start(config) const queue = 'clear-storage-works' const jobId = await boss.publish(queue) @@ -85,7 +78,7 @@ describe('deleteQueue', function () { const db = await helper.getDb() const getJobCount = async table => { - const jobCountResult = await db.executeSql(`SELECT count(*)::int as job_count FROM ${config.schema}.${table}`) + const jobCountResult = await db.executeSql(`SELECT count(*)::int as job_count FROM ${this.test.bossConfig.schema}.${table}`) return jobCountResult.rows[0].job_count } @@ -102,7 +95,5 @@ describe('deleteQueue', function () { assert(postJobCount === 0) assert(postArchiveCount === 0) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/deleteTest.js b/test/deleteTest.js index 8c8815f7..5bc7c5b1 100644 --- a/test/deleteTest.js +++ b/test/deleteTest.js @@ -12,7 +12,7 @@ describe('delete', async function () { const jobName = 'deleteMe' const config = { ...this.test.bossConfig, ...defaults } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) const jobId = await boss.publish(jobName) const job = await boss.fetch(jobName) @@ -25,7 +25,5 @@ describe('delete', async function () { const archivedJob = await helper.getArchivedJobById(config.schema, jobId) assert.strictEqual(archivedJob, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/errorTest.js b/test/errorTest.js index feba9d35..a9441665 100644 --- a/test/errorTest.js +++ b/test/errorTest.js @@ -1,31 +1,27 @@ const helper = require('./testHelper') describe('error', function () { - it('should handle an error in a subscriber and not blow up', function (finished) { - const config = this.test.bossConfig + it('should handle an error in a subscriber and not blow up', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - test() + const queue = 'error-handling' - async function test () { - const queue = 'error-handling' - let subscribeCount = 0 + let subscribeCount = 0 - const boss = await helper.start(config) - - await boss.publish(queue) - await boss.publish(queue) + await boss.publish(queue) + await boss.publish(queue) + return new Promise((resolve) => { boss.subscribe(queue, async job => { subscribeCount++ if (subscribeCount === 1) { throw new Error('test - nothing to see here') } else { - await job.done() - await boss.stop(this.test.bossConfig.stopOptions) - finished() + job.done() + resolve() } }) - } + }) }) }) diff --git a/test/expireTest.js b/test/expireTest.js index 1abdb3b6..0b09e14f 100644 --- a/test/expireTest.js +++ b/test/expireTest.js @@ -6,9 +6,10 @@ describe('expire', function () { const defaults = { maintenanceIntervalSeconds: 1 } it('should expire a job', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queue = 'expire' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const jobId = await boss.publish({ name: queue, options: { expireInSeconds: 1 } }) // fetch the job but don't complete it @@ -21,14 +22,13 @@ describe('expire', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('expired', job.data.state) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should expire a job - cascaded config', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, expireInSeconds: 1 }) + const queue = 'expire-cascade-config' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults, expireInSeconds: 1 }) const jobId = await boss.publish(queue) // fetch the job but don't complete it @@ -41,14 +41,12 @@ describe('expire', function () { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('expired', job.data.state) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should warn with an old expireIn option only once', async function () { - const queue = 'expireIn-warning-only-once' + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, noSupervisor: true }) - const boss = await helper.start({ ...this.test.bossConfig, noSupervisor: true }) + const queue = 'expireIn-warning-only-once' let warningCount = 0 @@ -67,7 +65,5 @@ describe('expire', function () { process.removeListener(warningEvent, onWarning) assert.strictEqual(warningCount, 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/failureTest.js b/test/failureTest.js index a994618c..16e21980 100644 --- a/test/failureTest.js +++ b/test/failureTest.js @@ -4,20 +4,19 @@ const helper = require('./testHelper') describe('failure', function () { it('should reject missing id argument', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.fail() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fail a job when requested', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'will-fail' await boss.publish(queue) @@ -25,14 +24,12 @@ describe('failure', function () { const job = await boss.fetch(queue) await boss.fail(job.id) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should subscribe to a job failure', async function () { - const queue = 'subscribe-fail' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'subscribe-fail' const jobId = await boss.publish(queue) const job = await boss.fetch(queue) @@ -43,17 +40,15 @@ describe('failure', function () { boss.onComplete(queue, async job => { assert.strictEqual(jobId, job.data.request.id) assert.strictEqual('failed', job.data.state) - - await boss.stop(this.test.bossConfig.stopOptions) resolve() }).catch(reject) }) }) it('should fail a batch of jobs', async function () { - const queue = 'complete-batch' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'complete-batch' await Promise.all([ boss.publish(queue), @@ -64,14 +59,14 @@ describe('failure', function () { const jobs = await boss.fetch(queue, 3) await boss.fail(jobs.map(job => job.id)) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept a payload', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'fail-payload' const failPayload = { someReason: 'nuna' } - const boss = await helper.start(this.test.bossConfig) const jobId = await boss.publish(queue) await boss.fail(jobId, failPayload) @@ -80,48 +75,38 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.someReason, failPayload.someReason) - - await boss.stop(this.test.bossConfig.stopOptions) }) - it('subscribe failure via done() should pass error payload to failed job', function (finished) { + it('subscribe failure via done() should pass error payload to failed job', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'fetchFailureWithPayload' const errorMessage = 'mah error' - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - await boss.publish(queue) + await boss.publish(queue) - boss.subscribe(queue, job => { + return new Promise((resolve) => { + boss.subscribe(queue, async job => { const error = new Error(errorMessage) - handler().catch(err => finished(err)) - - async function handler () { - await job.done(error) - - const failedJob = await boss.fetchCompleted(queue) + await job.done(error) - assert.strictEqual(failedJob.data.state, 'failed') - assert.strictEqual(failedJob.data.response.message, errorMessage) + const failedJob = await boss.fetchCompleted(queue) - await boss.stop(this.test.bossConfig.stopOptions) + assert.strictEqual(failedJob.data.state, 'failed') + assert.strictEqual(failedJob.data.response.message, errorMessage) - finished() - } + resolve() }) - } + }) }) it('subscribe failure via Promise reject() should pass string wrapped in value prop', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'subscribeFailureViaRejectString' const failPayload = 'mah error' - const boss = await helper.start(this.test.bossConfig) await boss.subscribe(queue, job => Promise.reject(failPayload)) await boss.publish(queue) @@ -131,18 +116,17 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.value, failPayload) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('subscribe failure via Promise reject() should pass object payload', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'subscribeFailureViaRejectObject' const something = 'clever' const errorResponse = new Error('custom error') errorResponse.something = something - const boss = await helper.start(this.test.bossConfig) await boss.subscribe(queue, job => Promise.reject(errorResponse)) await boss.publish(queue) @@ -152,15 +136,14 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert.strictEqual(job.data.response.something, something) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('failure with Error object should get stored in the failure job', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'failWithErrorObj' const message = 'a real error!' - const boss = await helper.start(this.test.bossConfig) await boss.publish(queue) await boss.subscribe(queue, async () => { throw new Error(message) }) @@ -170,7 +153,5 @@ describe('failure', function () { assert.strictEqual(job.data.state, 'failed') assert(job.data.response.message.includes(message)) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/fetchTest.js b/test/fetchTest.js index 62d5dd25..0dbf49ca 100644 --- a/test/fetchTest.js +++ b/test/fetchTest.js @@ -3,36 +3,32 @@ const helper = require('./testHelper') describe('fetch', function () { it('should reject missing queue argument', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.fetch() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fetch a job by name manually', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const jobName = 'no-subscribe-required' - const boss = await helper.start(this.test.bossConfig) await boss.publish(jobName) const job = await boss.fetch(jobName) assert(jobName === job.name) // Metadata should only be included when specifically requested assert(job.startedon === undefined) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should get a batch of jobs as an array', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const jobName = 'fetch-batch' const batchSize = 4 - const boss = await helper.start(this.test.bossConfig) - await Promise.all([ boss.publish(jobName), boss.publish(jobName), @@ -45,14 +41,12 @@ describe('fetch', function () { assert(jobs.length === batchSize) // Metadata should only be included when specifically requested assert(jobs[0].startedon === undefined) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch all metadata for a single job when requested', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const jobName = 'fetch-include-metadata' - const boss = await helper.start(this.test.bossConfig) await boss.publish(jobName) const job = await boss.fetch(jobName, undefined, { includeMetadata: true }) assert(jobName === job.name) @@ -70,15 +64,13 @@ describe('fetch', function () { assert(job.createdon !== undefined) assert(job.completedon === null) assert(job.keepuntil !== undefined) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should fetch all metadata for a batch of jobs when requested', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const jobName = 'fetch-include-metadata-batch' const batchSize = 4 - const boss = await helper.start(this.test.bossConfig) - await Promise.all([ boss.publish(jobName), boss.publish(jobName), @@ -106,6 +98,5 @@ describe('fetch', function () { assert(job.completedon === null) assert(job.keepuntil !== undefined) }) - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/global.js b/test/global.js index 35ec8344..fe951fdc 100644 --- a/test/global.js +++ b/test/global.js @@ -1,19 +1,28 @@ const helper = require('./testHelper') +const delay = require('delay') beforeEach(async function () { this.timeout(2000) - const config = helper.getConfig({ testKey: getTestKey(this) }) + const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) console.log(` - ${config.schema}`) await helper.dropSchema(config.schema) this.currentTest.bossConfig = config }) afterEach(async function () { - this.timeout(2000) - const config = helper.getConfig({ testKey: getTestKey(this) }) + this.timeout(5000) + + if (this.currentTest.boss) { + await helper.stop(this.currentTest.boss) + } + + await delay(2000) + + const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) + await helper.dropSchema(config.schema) }) function getTestKey (ctx) { - return ctx.currentTest.file + ctx.currentTest.parent.title + ctx.currentTest.title + return ctx.file + ctx.parent.title + ctx.title } diff --git a/test/maintenanceTest.js b/test/maintenanceTest.js index b9444dd7..b5e26aab 100644 --- a/test/maintenanceTest.js +++ b/test/maintenanceTest.js @@ -9,7 +9,7 @@ describe('maintenance', async function () { const db = await helper.getDb() - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) const queues = boss.boss.getQueueNames() const countJobs = () => helper.countJobs(config.schema, 'name = $1', [queues.MAINTENANCE]) @@ -26,7 +26,5 @@ describe('maintenance', async function () { const count = await countJobs() assert(count > 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/managerTest.js b/test/managerTest.js index 187206f7..18569807 100644 --- a/test/managerTest.js +++ b/test/managerTest.js @@ -1,10 +1,10 @@ const delay = require('delay') const assert = require('assert') -const PgBoss = require('../') +const helper = require('./testHelper') describe('manager', function () { it('should reject multiple simultaneous start requests', async function () { - const boss = new PgBoss(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) await boss.start() @@ -14,7 +14,7 @@ describe('manager', function () { await boss.start() assert(false) } catch (error) { - await boss.stop(this.test.bossConfig.stopOptions) + assert(true) } }) }) diff --git a/test/migrationTest.js b/test/migrationTest.js index ae5bb450..8c416bb3 100644 --- a/test/migrationTest.js +++ b/test/migrationTest.js @@ -34,15 +34,13 @@ describe('migration', function () { const config = { ...this.test.bossConfig, noSupervisor: true } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) await boss.start() const version = await contractor.version() assert.strictEqual(version, currentSchemaVersion) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should migrate through 2 versions back and forth', async function () { @@ -50,7 +48,7 @@ describe('migration', function () { const config = { ...this.test.bossConfig, noSupervisor: true } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) await boss.start() @@ -101,14 +99,12 @@ describe('migration', function () { assert.strictEqual(twoVersionsAgo, currentSchemaVersion - 2) const config = { ...this.test.bossConfig, noSupervisor: true } - const boss = new PgBoss(config) + const boss = this.test.boss = new PgBoss(config) await boss.start() const version = await contractor.version() assert.strictEqual(version, currentSchemaVersion) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('migrating to non-existent version fails gracefully', async function () { diff --git a/test/monitoringTest.js b/test/monitoringTest.js index 4855a877..057a7896 100644 --- a/test/monitoringTest.js +++ b/test/monitoringTest.js @@ -8,7 +8,7 @@ describe('monitoring', function () { maintenanceIntervalSeconds: 10 } - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const queue = 'monitorMe' @@ -51,8 +51,6 @@ describe('monitoring', function () { assert.strictEqual(states4.queues[queue].active, states.queues[queue].active, 'active count from monitor-states doesn\'t match') assert.strictEqual(states4.queues[queue].completed, states.queues[queue].completed, 'completed count from monitor-states doesn\'t match') - await boss.stop(this.test.bossConfig.stopOptions) - resolve() }) }) diff --git a/test/multiMasterTest.js b/test/multiMasterTest.js index 1c34c1af..932e33c0 100644 --- a/test/multiMasterTest.js +++ b/test/multiMasterTest.js @@ -88,7 +88,7 @@ describe('multi-master', function () { assert.strictEqual(beforeCount, jobCount) - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() boss = new PgBoss(this.test.bossConfig) @@ -100,6 +100,6 @@ describe('multi-master', function () { assert.strictEqual(completedCount, 1) - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() }) }) diff --git a/test/opsTest.js b/test/opsTest.js index f9db0d49..e8997592 100644 --- a/test/opsTest.js +++ b/test/opsTest.js @@ -5,28 +5,18 @@ describe('ops', function () { noSupervisor: true } - it('should start back up after stopping', async function () { - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) - await boss.stop(this.test.bossConfig.stopOptions) - await boss.start() - await boss.stop(this.test.bossConfig.stopOptions) - }) - it('should expire manually', async function () { - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.expire() - await boss.stop(this.test.bossConfig.stopOptions) }) it('should archive manually', async function () { - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.archive() - await boss.stop(this.test.bossConfig.stopOptions) }) it('should purge the archive manually', async function () { - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.purge() - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/priorityTest.js b/test/priorityTest.js index cde6b9ab..ce13c40e 100644 --- a/test/priorityTest.js +++ b/test/priorityTest.js @@ -3,9 +3,9 @@ const helper = require('./testHelper') describe('priority', function () { it('should process a newer higher priority job before an older lower priority job', async function () { - const jobName = 'priority-test' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const jobName = 'priority-test' await boss.publish(jobName) @@ -14,14 +14,12 @@ describe('priority', function () { const job = await boss.fetch(jobName) assert.strictEqual(job.id, high) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should process several jobs in descending priority order', async function () { - const queue = 'multiple-priority-test' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'multiple-priority-test' const low = await boss.publish(queue, null, { priority: 1 }) const medium = await boss.publish(queue, null, { priority: 5 }) @@ -34,7 +32,5 @@ describe('priority', function () { assert.strictEqual(job1.id, high) assert.strictEqual(job2.id, medium) assert.strictEqual(job3.id, low) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/publishTest.js b/test/publishTest.js index fa9cd447..4cd1829d 100644 --- a/test/publishTest.js +++ b/test/publishTest.js @@ -3,82 +3,71 @@ const helper = require('./testHelper') describe('publish', function () { it('should fail with no arguments', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.publish() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fail with a function for data', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.publish('job', () => true) assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fail with a function for options', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.publish('job', 'data', () => true) assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should accept single string argument', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'publishNameOnly' await boss.publish(queue) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object argument with only name', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'publishqueueOnly' await boss.publish({ name: queue }) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object with name and data only', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'publishqueueAndData' const message = 'hi' - const boss = await helper.start(this.test.bossConfig) await boss.publish({ name: queue, data: { message } }) const job = await boss.fetch(queue) assert.strictEqual(message, job.data.message) - await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept job object with name and options only', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'publishqueueAndOptions' const options = { someCrazyOption: 'whatever' } - const boss = await helper.start(this.test.bossConfig) await boss.publish({ name: queue, options }) const job = await boss.fetch(queue) assert.strictEqual(job.data, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/retryTest.js b/test/retryTest.js index 704011ec..5f1878de 100644 --- a/test/retryTest.js +++ b/test/retryTest.js @@ -6,9 +6,10 @@ describe('retries', function () { const defaults = { maintenanceIntervalSeconds: 1 } it('should retry a job that didn\'t complete', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queue = 'unreliable' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const jobId = await boss.publish({ name: queue, options: { expireInSeconds: 1, retryLimit: 1 } }) const try1 = await boss.fetch(queue) @@ -19,15 +20,14 @@ describe('retries', function () { assert.strictEqual(try1.id, jobId) assert.strictEqual(try2.id, jobId) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry a job that failed', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queueName = 'retryFailed' const retryLimit = 1 - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const jobId = await boss.publish(queueName, null, { retryLimit }) await boss.fetch(queueName) @@ -36,15 +36,14 @@ describe('retries', function () { const job = await boss.fetch(queueName) assert.strictEqual(job.id, jobId) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry a job that failed with cascaded config', async function () { - const queueName = 'retryFailed-config-cascade' const retryLimit = 1 + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, retryLimit }) + + const queueName = 'retryFailed-config-cascade' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults, retryLimit }) const jobId = await boss.publish(queueName) await boss.fetch(queueName) @@ -53,14 +52,13 @@ describe('retries', function () { const job = await boss.fetch(queueName) assert.strictEqual(job.id, jobId) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry with a fixed delay', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queue = 'retryDelayFixed' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const jobId = await boss.publish(queue, null, { retryLimit: 1, retryDelay: 1 }) await boss.fetch(queue) @@ -75,32 +73,31 @@ describe('retries', function () { const job2 = await boss.fetch(queue) assert(job2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should retry with a exponential backoff', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queue = 'retryDelayBackoff' let subscribeCount = 0 const retryLimit = 4 - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.subscribe(queue, { newJobCheckInterval: 500 }, job => job.done(++subscribeCount)) await boss.publish(queue, null, { retryLimit, retryBackoff: true }) await delay(9000) assert(subscribeCount < retryLimit) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should set the default retry limit to 1 if missing', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const queue = 'retryLimitDefault' - const boss = await helper.start({ ...this.test.bossConfig, ...defaults }) const jobId = await boss.publish(queue, null, { retryDelay: 1 }) + await boss.fetch(queue) await boss.fail(jobId) @@ -113,7 +110,5 @@ describe('retries', function () { const job2 = await boss.fetch(queue) assert(job2) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/scheduleTest.js b/test/scheduleTest.js index 68697c37..bb2c5498 100644 --- a/test/scheduleTest.js +++ b/test/scheduleTest.js @@ -9,9 +9,9 @@ const ASSERT_DELAY = 9000 describe('schedule', function () { it('should publish job based on every minute expression', async function () { - const queue = 'schedule-every-min' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'schedule-every-min' await boss.schedule(queue, '* * * * *') @@ -20,19 +20,17 @@ describe('schedule', function () { const job = await boss.fetch(queue) assert(job) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should accept a custom clock monitoring interval in seconds', async function () { - const queue = 'schedule-custom-monitoring-seconds' - const config = { ...this.test.bossConfig, clockMonitorIntervalSeconds: 1 } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) + + const queue = 'schedule-custom-monitoring-seconds' await boss.schedule(queue, '* * * * *') @@ -41,19 +39,17 @@ describe('schedule', function () { const job = await boss.fetch(queue) assert(job) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('cron monitoring should restart cron if paused', async function () { - const queue = 'schedule-cron-monitoring' - const config = { ...this.test.bossConfig, cronMonitorIntervalSeconds: 1 } - const boss = await helper.start(config) + const boss = this.test.boss = await helper.start(config) + + const queue = 'schedule-cron-monitoring' const { schema } = this.test.bossConfig const db = await helper.getDb() @@ -67,20 +63,18 @@ describe('schedule', function () { const job = await boss.fetch(queue) assert(job) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should publish job based on every minute expression after a restart', async function () { const queue = 'schedule-every-min-restart' - let boss = await helper.start({ ...this.test.bossConfig, noScheduling: true }) + let boss = await helper.start({ ...this.test.bossConfig, noScheduling: true, noSupervisor: true }) await boss.schedule(queue, '* * * * *') - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() - boss = await helper.start(this.test.bossConfig) + boss = await helper.start({ ...this.test.bossConfig, noSupervisor: true }) await delay(ASSERT_DELAY) @@ -88,19 +82,19 @@ describe('schedule', function () { assert(job) - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() }) it('should remove previously scheduled job', async function () { const queue = 'schedule-remove' - const boss = await helper.start(this.test.bossConfig) + const boss = await helper.start({ ...this.test.bossConfig, noSupervisor: true }) await boss.schedule(queue, '* * * * *') await boss.unschedule(queue) - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() const db = await helper.getDb() await db.executeSql(plans.clearStorage(this.test.bossConfig.schema)) @@ -113,10 +107,12 @@ describe('schedule', function () { assert(job === null) - await boss.stop(this.test.bossConfig.stopOptions) + await boss.stop() }) it('should publish job based on current minute in UTC', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'schedule-current-min-utc' const now = new Date() @@ -130,8 +126,6 @@ describe('schedule', function () { // using current and next minute because the clock is ticking const minuteExpression = `${currentMinute},${nextMinute}` - const boss = await helper.start(this.test.bossConfig) - await boss.schedule(queue, `${minuteExpression} * * * *`) await delay(ASSERT_DELAY) @@ -139,11 +133,11 @@ describe('schedule', function () { const job = await boss.fetch(queue) assert(job) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should publish job based on current minute in a specified time zone', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'schedule-current-min-timezone' const tz = 'America/Los_Angeles' @@ -162,8 +156,6 @@ describe('schedule', function () { const minute = `${currentMinute},${nextMinute}` const hour = `${currentHour},${nextHour}` - const boss = await helper.start(this.test.bossConfig) - await boss.schedule(queue, `${minute} ${hour} * * *`, null, { tz }) await delay(ASSERT_DELAY) @@ -171,12 +163,10 @@ describe('schedule', function () { const job = await boss.fetch(queue) assert(job) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should force a clock skew warning', async function () { - const boss = new PgBoss({ ...this.test.bossConfig, __test__force_clock_skew_warning: true }) + const boss = this.test.boss = new PgBoss({ ...this.test.bossConfig, __test__force_clock_skew_warning: true }) let warningCount = 0 @@ -193,7 +183,5 @@ describe('schedule', function () { process.removeListener(warningEvent, onWarning) assert.strictEqual(warningCount, 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/singletonTest.js b/test/singletonTest.js index 91a84565..4db94c66 100644 --- a/test/singletonTest.js +++ b/test/singletonTest.js @@ -3,10 +3,11 @@ const helper = require('./testHelper') describe('singleton', function () { it('should not allow more than 1 pending job at a time with the same key', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'singleton-1-pending' const singletonKey = 'a' - const boss = await helper.start(this.test.bossConfig) const jobId = await boss.publish(queue, null, { singletonKey }) assert(jobId) @@ -14,16 +15,15 @@ describe('singleton', function () { const jobId2 = await boss.publish(queue, null, { singletonKey }) assert.strictEqual(jobId2, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should not allow more than 1 complete job with the same key with an interval', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'singleton-1-complete' const singletonKey = 'a' const singletonMinutes = 1 - const boss = await helper.start(this.test.bossConfig) await boss.publish(queue, null, { singletonKey, singletonMinutes }) const job = await boss.fetch(queue) @@ -32,14 +32,12 @@ describe('singleton', function () { const jobId = await boss.publish(queue, null, { singletonKey, singletonMinutes }) assert.strictEqual(jobId, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should allow more than 1 pending job at the same time with different keys', async function () { - const queue = 'singleton' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'singleton' const jobId = await boss.publish(queue, null, { singletonKey: 'a' }) assert(jobId) @@ -47,15 +45,14 @@ describe('singleton', function () { const jobId2 = await boss.publish(queue, null, { singletonKey: 'b' }) assert(jobId2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('publishOnce() should work', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'publishOnce' const key = 'only-once-plz' - const boss = await helper.start(this.test.bossConfig) const jobId = await boss.publishOnce(queue, null, null, key) assert(jobId) @@ -63,14 +60,12 @@ describe('singleton', function () { const jobId2 = await boss.publishOnce(queue, null, null, key) assert.strictEqual(jobId2, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('publishOnce() without a key should also work', async function () { - const queue = 'publishOnceNoKey' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'publishOnceNoKey' const jobId = await boss.publishOnce(queue) assert(jobId) @@ -78,7 +73,5 @@ describe('singleton', function () { const jobId2 = await boss.publishOnce(queue) assert.strictEqual(jobId2, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/speedTest.js b/test/speedTest.js index 983dd5f6..9da115d1 100644 --- a/test/speedTest.js +++ b/test/speedTest.js @@ -18,7 +18,7 @@ describe('speed', function () { await pMap(jobs, job => boss.publish(job.name, job.data)) }) - afterEach(async function () { await boss.stop(this.test.bossConfig.stopOptions) }) + afterEach(async function () { await helper.stop(boss) }) it(testTitle, async function () { this.timeout(expectedSeconds * 1000) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index fd7d5e87..1a35b7b3 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -4,66 +4,58 @@ const helper = require('./testHelper') describe('subscribe', function () { it('should fail with no arguments', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.subscribe() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fail if no callback provided', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.subscribe('foo') assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should fail if options is not an object', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.subscribe('foo', () => {}, 'nope') assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('unsubscribe should fail without a name', async function () { - const boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start(this.test.bossConfig) try { await boss.unsubscribe() assert(false) } catch (err) { assert(err) - } finally { - await boss.stop(this.test.bossConfig.stopOptions) } }) it('should honor a custom new job check interval', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'customJobCheckInterval' const newJobCheckIntervalSeconds = 3 const timeout = 9000 let subscribeCount = 0 const jobCount = 10 - const boss = await helper.start(this.test.bossConfig) - for (let i = 0; i < jobCount; i++) { await boss.publish(queue) } @@ -73,17 +65,15 @@ describe('subscribe', function () { await delay(timeout) assert(subscribeCount <= timeout / 1000 / newJobCheckIntervalSeconds) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should unsubscribe a subscription', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'unsubscribe-works' let receivedCount = 0 - const boss = await helper.start(this.test.bossConfig) - boss.subscribe(queue, async () => { receivedCount++ await boss.unsubscribe(queue) @@ -95,20 +85,16 @@ describe('subscribe', function () { await delay(5000) assert.strictEqual(receivedCount, 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should handle a batch of jobs via teamSize', async function () { - this.timeout(1000) + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'subscribe-teamSize' const teamSize = 4 let subscribeCount = 0 - const boss = await helper.start(this.test.bossConfig) - for (let i = 0; i < teamSize; i++) { await boss.publish(queue) } @@ -119,15 +105,14 @@ describe('subscribe', function () { // test would time out if it had to wait for 4 fetch intervals if (subscribeCount === teamSize) { - await boss.stop(this.test.bossConfig.stopOptions) resolve() } }).catch(reject) }) }) - it('should apply teamConcurrency option', function (finished) { - this.timeout(1000) + it('should apply teamConcurrency option', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'subscribe-teamConcurrency' const teamSize = 4 @@ -135,61 +120,49 @@ describe('subscribe', function () { let subscribeCount = 0 - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - - for (let i = 0; i < teamSize; i++) { - await boss.publish(queue) - } + for (let i = 0; i < teamSize; i++) { + await boss.publish(queue) + } + return new Promise((resolve) => { boss.subscribe(queue, { teamSize, teamConcurrency }, async () => { subscribeCount++ if (subscribeCount === teamSize) { - await boss.stop(this.test.bossConfig.stopOptions) - finished() + resolve() } // test would time out if it had to wait for each handler to resolve await delay(4000) }) - } + }) }) - it('should handle a batch of jobs via batchSize', function (finished) { + it('should handle a batch of jobs via batchSize', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'subscribe-batchSize' const batchSize = 4 - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - - for (let i = 0; i < batchSize; i++) { - await boss.publish(queue) - } + for (let i = 0; i < batchSize; i++) { + await boss.publish(queue) + } + return new Promise((resolve) => { boss.subscribe(queue, { batchSize }, async jobs => { assert.strictEqual(jobs.length, batchSize) - await boss.stop(this.test.bossConfig.stopOptions) - finished() - }).catch(finished) - } + resolve() + }) + }) }) it('returning promise applies backpressure', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'backpressure' + const batchSize = 4 let subscribeCount = 0 - const boss = await helper.start(this.test.bossConfig) - for (let i = 0; i < batchSize; i++) { await boss.publish(queue) } @@ -203,113 +176,78 @@ describe('subscribe', function () { await delay(7000) assert(subscribeCount < batchSize) - - await boss.stop(this.test.bossConfig.stopOptions) }) - it('should have a done callback for single job subscriptions', function (finished) { + it('should have a done callback for single job subscriptions', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'subscribe-single' - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - await boss.publish(queue) + await boss.publish(queue) + return new Promise((resolve) => { boss.subscribe(queue, async job => { - await job.done() - await boss.stop(this.test.bossConfig.stopOptions) - finished() + job.done() + resolve() }) - } + }) }) - it('subscribe completion should pass string wrapped in value prop', function (finished) { + it('subscribe completion should pass string wrapped in value prop', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'subscribeCompletionString' const result = 'success' - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - - boss.subscribe(queue, async job => result) - - await boss.publish(queue) - - await delay(8000) + boss.subscribe(queue, async job => result) - const job = await boss.fetchCompleted(queue) + await boss.publish(queue) - assert.strictEqual(job.data.state, 'completed') - assert.strictEqual(job.data.response.value, result) + await delay(8000) - await boss.stop(this.test.bossConfig.stopOptions) + const job = await boss.fetchCompleted(queue) - finished() - } + assert.strictEqual(job.data.state, 'completed') + assert.strictEqual(job.data.response.value, result) }) - it('subscribe completion via Promise resolve() should pass object payload', function (finished) { + it('subscribe completion via Promise resolve() should pass object payload', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'subscribeCompletionObject' const something = 'clever' - const config = this.test.bossConfig - - test() - - async function test () { - const boss = await helper.start(config) - - boss.subscribe(queue, async job => ({ something })) + boss.subscribe(queue, async job => ({ something })) - await boss.publish(queue) - - await delay(8000) - - const job = await boss.fetchCompleted(queue) + await boss.publish(queue) - assert.strictEqual(job.data.state, 'completed') - assert.strictEqual(job.data.response.something, something) + await delay(8000) - await boss.stop(this.test.bossConfig.stopOptions) + const job = await boss.fetchCompleted(queue) - finished() - } + assert.strictEqual(job.data.state, 'completed') + assert.strictEqual(job.data.response.something, something) }) it('should allow multiple subscriptions to the same queue per instance', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'multiple-subscriptions' - const boss = await helper.start(this.test.bossConfig) - await boss.subscribe(queue, () => {}) await boss.subscribe(queue, () => {}) - - await boss.stop(this.test.bossConfig.stopOptions) }) - it('should honor the includeMetadata option', function (finished) { - const queue = 'subscribe-includeMetadata' - - const config = this.test.bossConfig - - test() + it('should honor the includeMetadata option', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - async function test () { - const boss = await helper.start(config) + const queue = 'subscribe-includeMetadata' - await boss.publish(queue) + await boss.publish(queue) + return new Promise((resolve) => { boss.subscribe(queue, { includeMetadata: true }, async job => { assert(job.startedon !== undefined) - await boss.stop(this.test.bossConfig.stopOptions) - finished() - }).catch(finished) - } + resolve() + }) + }) }) }) diff --git a/test/testHelper.js b/test/testHelper.js index 049a3995..81a6c317 100644 --- a/test/testHelper.js +++ b/test/testHelper.js @@ -7,6 +7,7 @@ const sha1 = (value) => crypto.createHash('sha1').update(value).digest('hex') module.exports = { dropSchema, start, + stop, getDb, getJobById, getArchivedJobById, @@ -39,8 +40,6 @@ function getConfig (options = {}) { config.schema = config.schema || 'pgboss' - config.stopOptions = { graceful: false } - const result = { ...config } return Object.assign(result, options) @@ -122,6 +121,7 @@ async function start (options) { try { options = getConfig(options) const boss = new PgBoss(options) + boss.on('error', err => console.log({ schema: options.schema, message: err.message })) await boss.start() return boss } catch (err) { @@ -131,3 +131,7 @@ async function start (options) { } } } + +async function stop (boss) { + await boss.stop({ timeout: 4000 }) +} diff --git a/test/throttleTest.js b/test/throttleTest.js index 6db7dd2f..c4ec08c0 100644 --- a/test/throttleTest.js +++ b/test/throttleTest.js @@ -4,6 +4,8 @@ const delay = require('delay') describe('throttle', function () { it('should only create 1 job for interval with a delay', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'delayThrottle' const singletonSeconds = 4 const startAfter = 2 @@ -12,8 +14,6 @@ describe('throttle', function () { let subscribeCount = 0 - const boss = await helper.start(this.test.bossConfig) - boss.subscribe(queue, async () => subscribeCount++) for (let i = 0; i < publishCount; i++) { @@ -24,11 +24,11 @@ describe('throttle', function () { await delay(singletonSeconds * 1000) assert(subscribeCount <= 2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should process at most 1 job per second', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'throttle-1ps' const singletonSeconds = 1 const jobCount = 3 @@ -38,8 +38,6 @@ describe('throttle', function () { const publishCount = 0 let subscribeCount = 0 - const boss = await helper.start(this.test.bossConfig) - boss.subscribe(queue, async () => subscribeCount++) for (let i = 0; i < publishCount; i++) { @@ -50,14 +48,12 @@ describe('throttle', function () { await delay(assertTimeout) assert(subscribeCount <= jobCount + 1) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should debounce', async function () { - const queue = 'debounce' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'debounce' const jobId = await boss.publish(queue, null, { singletonHours: 1 }) @@ -66,16 +62,14 @@ describe('throttle', function () { const jobId2 = await boss.publish(queue, null, { singletonHours: 1, singletonNextSlot: true }) assert(jobId2) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should debounce via publishDebounced()', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'publishDebounced' const seconds = 60 - const boss = await helper.start(this.test.bossConfig) - const jobId = await boss.publishDebounced(queue, null, null, seconds) assert(jobId) @@ -87,14 +81,12 @@ describe('throttle', function () { const jobId3 = await boss.publishDebounced(queue, null, null, seconds) assert.strictEqual(jobId3, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should reject 2nd request in the same time slot', async function () { - const queue = 'throttle-reject-2nd' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const queue = 'throttle-reject-2nd' const jobId1 = await boss.publish(queue, null, { singletonHours: 1 }) @@ -103,16 +95,14 @@ describe('throttle', function () { const jobId2 = await boss.publish(queue, null, { singletonHours: 1 }) assert.strictEqual(jobId2, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) it('should throttle via publishThrottled()', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'throttle-reject-2nd-publishThrottled' const seconds = 60 - const boss = await helper.start(this.test.bossConfig) - const jobId1 = await boss.publishThrottled(queue, null, null, seconds) assert(jobId1) @@ -120,7 +110,5 @@ describe('throttle', function () { const jobId2 = await boss.publishThrottled(queue, null, null, seconds) assert.strictEqual(jobId2, null) - - await boss.stop(this.test.bossConfig.stopOptions) }) }) diff --git a/test/wildcardTest.js b/test/wildcardTest.js index 0c81dbcc..a9bf1fed 100644 --- a/test/wildcardTest.js +++ b/test/wildcardTest.js @@ -3,9 +3,10 @@ const helper = require('./testHelper') describe('wildcard', function () { it('fetch() should return all jobs using a wildcard pattern', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = 'wildcard-fetch' - const boss = await helper.start(this.test.bossConfig) await boss.publish(`${queue}_1234`) await boss.publish(`${queue}_5678`) @@ -14,29 +15,26 @@ describe('wildcard', function () { assert.strictEqual(jobs.length, 2) }) - it('subscribe() should return all jobs using a wildcard pattern', function (finished) { - const baseName = 'wildcard-subscribe' - const config = this.test.bossConfig - - test() + it('subscribe() should return all jobs using a wildcard pattern', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) - async function test () { - const boss = await helper.start(config) + const baseName = 'wildcard-subscribe' - await boss.publish(`${baseName}_1234`) - await boss.publish(`${baseName}_5678`) + await boss.publish(`${baseName}_1234`) + await boss.publish(`${baseName}_5678`) + return new Promise((resolve) => { boss.subscribe(`${baseName}_*`, { batchSize: 2 }, jobs => { assert.strictEqual(jobs.length, 2) - boss.stop(this.test.bossConfig.stopOptions).then(() => finished()) + resolve() }) - } + }) }) it('should not accidentally fetch state completion jobs from a pattern', async function () { - const baseName = 'wildcard-fetch-incomplete' + const boss = this.test.boss = await helper.start(this.test.bossConfig) - const boss = await helper.start(this.test.bossConfig) + const baseName = 'wildcard-fetch-incomplete' await boss.publish(`${baseName}_1234`) const job = await boss.fetch(`${baseName}_*`) @@ -44,6 +42,5 @@ describe('wildcard', function () { const job2 = await boss.fetch(`${baseName}_*`) assert.strictEqual(job2, null) - await boss.stop(this.test.bossConfig.stopOptions) }) }) From 08ae2aa1d1186e2928c7cb4078dc8135a4bdab1f Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Sat, 1 May 2021 14:22:06 -0500 Subject: [PATCH 07/19] test hook fixes --- src/boss.js | 11 ++++--- src/index.js | 22 +++++++++----- src/manager.js | 26 ++++++++++------- src/timekeeper.js | 8 ++--- test/backgroundErrorTest.js | 58 +++++++++++++++++++++++++------------ test/global.js | 18 +++++++----- test/monitoringTest.js | 19 +++++++----- test/multiMasterTest.js | 2 -- test/testHelper.js | 4 +-- 9 files changed, 100 insertions(+), 68 deletions(-) diff --git a/src/boss.js b/src/boss.js index 39334963..03859588 100644 --- a/src/boss.js +++ b/src/boss.js @@ -29,7 +29,6 @@ class Boss extends EventEmitter { this.monitorIntervalSeconds = config.monitorStateIntervalSeconds } - this.queues = queues this.events = events this.expireCommand = plans.expire(config.schema) @@ -137,7 +136,6 @@ class Boss extends EventEmitter { } } catch (err) { this.emit(events.error, err) - throw err } } @@ -162,16 +160,16 @@ class Boss extends EventEmitter { async stop () { if (!this.stopped) { + if (this.metaMonitorInterval) { + clearInterval(this.metaMonitorInterval) + } + await this.manager.unsubscribe(queues.MAINTENANCE) if (this.monitorStates) { await this.manager.unsubscribe(queues.MONITOR_STATES) } - if (this.metaMonitorInterval) { - clearInterval(this.metaMonitorInterval) - } - this.stopped = true } } @@ -243,3 +241,4 @@ class Boss extends EventEmitter { } module.exports = Boss +module.exports.QUEUES = queues diff --git a/src/index.js b/src/index.js index 5b5463b7..12ba33c1 100644 --- a/src/index.js +++ b/src/index.js @@ -52,6 +52,8 @@ class PgBoss extends EventEmitter { manager.timekeeper = timekeeper + this.stoppingOn = null + this.stopped = true this.config = config this.db = db this.boss = boss @@ -71,7 +73,7 @@ class PgBoss extends EventEmitter { function promoteFunction (obj, func) { this[func.name] = (...args) => { - if (!this.isStarted || this.stoppingOn) { + if (this.stopped || this.stoppingOn) { const state = this.stoppingOn ? 'stopping' : 'stopped' return Promise.reject(new Error(`pg-boss is ${state}.`)) } @@ -86,10 +88,12 @@ class PgBoss extends EventEmitter { } async start () { - if (this.isStarted) { + if (!this.stopped) { return this } + this.stopped = false + if (this.db.isOurs && !this.db.opened) { await this.db.open() } @@ -104,23 +108,25 @@ class PgBoss extends EventEmitter { await this.timekeeper.start() } - this.isStarted = true - return this } async stop (options = {}) { - if (!this.isStarted || this.stoppingOn) { + if (this.stoppingOn) { return } + if (this.stopped) { + this.emit(events.stopped) + } + let { graceful = true, timeout = 30000 } = options timeout = Math.max(timeout, 1000) this.stoppingOn = Date.now() - await this.manager.stop({ not: this.boss.queues.MAINTENANCE }) + await this.manager.stop() await this.timekeeper.stop() let polling = false @@ -139,7 +145,7 @@ class PgBoss extends EventEmitter { throw err } } finally { - this.isStarted = false + this.stopped = true this.stoppingOn = null this.emit(events.stopped) @@ -158,7 +164,7 @@ class PgBoss extends EventEmitter { setImmediate(async () => { while (Date.now() - this.stoppingOn < timeout) { - await delay(2000) + await delay(1000) if (this.manager.getWipData().length === 0) { return await shutdown() diff --git a/src/manager.js b/src/manager.js index 320db4ba..252adcb1 100644 --- a/src/manager.js +++ b/src/manager.js @@ -7,6 +7,9 @@ const debounce = require('lodash.debounce') const Attorney = require('./attorney') const Worker = require('./worker') +const { QUEUES: BOSS_QUEUES } = require('./boss') +const HIDDEN_QUEUES = Object.values(BOSS_QUEUES) + const plans = require('./plans') const { COMPLETION_JOB_PREFIX } = plans @@ -57,11 +60,9 @@ class Manager extends EventEmitter { ] } - async stop (options = {}) { - const { not = null } = options - + async stop () { for (const sub of this.subscriptions.values()) { - if (not && not === sub.name) { + if (HIDDEN_QUEUES.includes(sub.name)) { continue } @@ -118,7 +119,7 @@ class Manager extends EventEmitter { lastError, lastErrorOn })) - .filter(i => i.count > 0) + .filter(i => i.count > 0 && !HIDDEN_QUEUES.includes(i.name)) return data } @@ -155,7 +156,6 @@ class Manager extends EventEmitter { } const onError = error => { - console.log(error) // todo: remove this.emit(events.error, { ...error, queue: name, worker: id }) } @@ -195,7 +195,7 @@ class Manager extends EventEmitter { this.removeWorker(worker) } } - }, 2000) + }, 1000) } async offComplete (name) { @@ -282,7 +282,7 @@ class Manager extends EventEmitter { const result = await this.db.executeSql(this.insertJobCommand, values) - if (result.rowCount === 1) { + if (result && result.rowCount === 1) { return result.rows[0].id } @@ -325,6 +325,10 @@ class Manager extends EventEmitter { [values.name, batchSize || 1] ) + if (!result) { + return null + } + const jobs = result.rows.map(job => { job.done = async (error, response) => { if (error) { @@ -373,7 +377,7 @@ class Manager extends EventEmitter { return { jobs: ids, requested: ids.length, - updated: parseInt(result.rows[0].count) + updated: result && result.rows ? parseInt(result.rows[0].count) : 0 } } @@ -399,13 +403,13 @@ class Manager extends EventEmitter { assert(queue, 'Missing queue name argument') const sql = plans.deleteQueue(this.config.schema, options) const result = await this.db.executeSql(sql, [queue]) - return result.rowCount + return result ? result.rowCount : null } async deleteAllQueues (options) { const sql = plans.deleteAllQueues(this.config.schema, options) const result = await this.db.executeSql(sql) - return result.rowCount + return result ? result.rowCount : null } async clearStorage () { diff --git a/src/timekeeper.js b/src/timekeeper.js index c6738910..470f69b5 100644 --- a/src/timekeeper.js +++ b/src/timekeeper.js @@ -184,14 +184,14 @@ class Timekeeper extends EventEmitter { const values = [name, cron, tz, data, options] - const { rowCount } = await this.db.executeSql(this.scheduleCommand, values) + const result = await this.db.executeSql(this.scheduleCommand, values) - return rowCount + return result ? result.rowCount : null } async unschedule (name) { - const { rowCount } = await this.db.executeSql(this.unscheduleCommand, [name]) - return rowCount + const result = await this.db.executeSql(this.unscheduleCommand, [name]) + return result ? result.rowCount : null } async setCronTime () { diff --git a/test/backgroundErrorTest.js b/test/backgroundErrorTest.js index a1061c7c..d7f34a55 100644 --- a/test/backgroundErrorTest.js +++ b/test/backgroundErrorTest.js @@ -1,51 +1,71 @@ const PgBoss = require('../') describe('background processing error handling', function () { - it('maintenance error handling works', function (done) { + it('maintenance error handling works', async function () { const defaults = { monitorStateIntervalMinutes: 1, maintenanceIntervalSeconds: 1, + noScheduling: true, __test__throw_maint: true } const config = { ...this.test.bossConfig, ...defaults } const boss = this.test.boss = new PgBoss(config) - boss.on('error', async () => { - boss.removeAllListeners() - done() - }) + return new Promise((resolve) => { + let resolved = false + + boss.on('error', () => { + if (!resolved) { + resolved = true + resolve() + } + }) - boss.start() + boss.start().then(() => {}) + }) }) - it('state monitoring error handling works', function (done) { + it('state monitoring error handling works', async function () { const defaults = { - monitorStateIntervalSeconds: 1, + monitorStateIntervalSeconds: 2, maintenanceIntervalMinutes: 1, + noScheduling: true, __test__throw_monitor: true } const config = { ...this.test.bossConfig, ...defaults } const boss = this.test.boss = new PgBoss(config) - boss.on('error', async () => { - boss.removeAllListeners() - done() - }) + return new Promise((resolve) => { + let resolved = false + + boss.on('error', () => { + if (!resolved) { + resolved = true + resolve() + } + }) - boss.start() + boss.start().then(() => {}) + }) }) - it('clock monitoring error handling works', function (done) { + it('clock monitoring error handling works', async function () { const config = { ...this.test.bossConfig, __test__throw_clock_monitoring: true } const boss = this.test.boss = new PgBoss(config) - boss.on('error', async () => { - boss.removeAllListeners() - done() - }) + return new Promise((resolve) => { + let resolved = false - boss.start() + boss.on('error', () => { + if (!resolved) { + resolved = true + resolve() + } + }) + + boss.start().then(() => {}) + }) }) }) diff --git a/test/global.js b/test/global.js index fe951fdc..d5d14f5d 100644 --- a/test/global.js +++ b/test/global.js @@ -1,24 +1,26 @@ const helper = require('./testHelper') -const delay = require('delay') beforeEach(async function () { this.timeout(2000) const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) - console.log(` - ${config.schema}`) + console.log(` ${this.currentTest.title} (schema: ${config.schema})...`) await helper.dropSchema(config.schema) this.currentTest.bossConfig = config }) afterEach(async function () { - this.timeout(5000) + this.timeout(10000) - if (this.currentTest.boss) { - await helper.stop(this.currentTest.boss) - } + const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) - await delay(2000) + const { boss } = this.currentTest - const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) + if (boss) { + await new Promise((resolve) => { + boss.on('stopped', resolve) + helper.stop(boss, 2000) + }) + } await helper.dropSchema(config.schema) }) diff --git a/test/monitoringTest.js b/test/monitoringTest.js index 057a7896..938af164 100644 --- a/test/monitoringTest.js +++ b/test/monitoringTest.js @@ -43,15 +43,18 @@ describe('monitoring', function () { assert.strictEqual(2, states4.queues[queue].active, 'active count is wrong after 3 publishes and 3 fetches and 1 complete') assert.strictEqual(1, states4.queues[queue].completed, 'completed count is wrong after 3 publishes and 3 fetches and 1 complete') - return new Promise((resolve, reject) => { - boss.on('monitor-states', async states => { - boss.removeAllListeners() - - assert.strictEqual(states4.queues[queue].created, states.queues[queue].created, 'created count from monitor-states doesn\'t match') - assert.strictEqual(states4.queues[queue].active, states.queues[queue].active, 'active count from monitor-states doesn\'t match') - assert.strictEqual(states4.queues[queue].completed, states.queues[queue].completed, 'completed count from monitor-states doesn\'t match') + return new Promise((resolve) => { + let resolved = false - resolve() + boss.on('monitor-states', async states => { + if (!resolved) { + resolved = true + assert.strictEqual(states4.queues[queue].created, states.queues[queue].created, 'created count from monitor-states doesn\'t match') + assert.strictEqual(states4.queues[queue].active, states.queues[queue].active, 'active count from monitor-states doesn\'t match') + assert.strictEqual(states4.queues[queue].completed, states.queues[queue].completed, 'completed count from monitor-states doesn\'t match') + + resolve() + } }) }) }) diff --git a/test/multiMasterTest.js b/test/multiMasterTest.js index 932e33c0..125dd9c8 100644 --- a/test/multiMasterTest.js +++ b/test/multiMasterTest.js @@ -20,7 +20,6 @@ describe('multi-master', function () { try { await pMap(instances, i => i.start()) } catch (err) { - console.log(err.message) assert(false) } finally { await pMap(instances, i => i.stop()) @@ -54,7 +53,6 @@ describe('multi-master', function () { try { await pMap(instances, i => i.start()) } catch (err) { - console.log(err.message) assert(false) } finally { await pMap(instances, i => i.stop()) diff --git a/test/testHelper.js b/test/testHelper.js index 81a6c317..2ca8f253 100644 --- a/test/testHelper.js +++ b/test/testHelper.js @@ -132,6 +132,6 @@ async function start (options) { } } -async function stop (boss) { - await boss.stop({ timeout: 4000 }) +async function stop (boss, timeout = 4000) { + await boss.stop({ timeout }) } From 69df52080809b335f956a1257844ccd33f3a4fa8 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Sat, 1 May 2021 16:02:12 -0500 Subject: [PATCH 08/19] fix test suite --- src/boss.js | 5 +++-- test/completeTest.js | 2 +- test/testHelper.js | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/boss.js b/src/boss.js index 03859588..57fadad0 100644 --- a/src/boss.js +++ b/src/boss.js @@ -1,6 +1,7 @@ const EventEmitter = require('events') const plans = require('./plans') const { states } = require('./plans') +const { COMPLETION_JOB_PREFIX } = plans const queues = { MAINTENANCE: '__pgboss__maintenance', @@ -50,7 +51,7 @@ class Boss extends EventEmitter { async supervise () { this.metaMonitor() - await this.manager.deleteQueue(plans.completedJobPrefix + queues.MAINTENANCE) + await this.manager.deleteQueue(COMPLETION_JOB_PREFIX + queues.MAINTENANCE) await this.manager.deleteQueue(queues.MAINTENANCE) await this.maintenanceAsync() @@ -62,7 +63,7 @@ class Boss extends EventEmitter { await this.manager.subscribe(queues.MAINTENANCE, maintenanceSubscribeOptions, (job) => this.onMaintenance(job)) if (this.monitorStates) { - await this.manager.deleteQueue(plans.completedJobPrefix + queues.MONITOR_STATES) + await this.manager.deleteQueue(COMPLETION_JOB_PREFIX + queues.MONITOR_STATES) await this.manager.deleteQueue(queues.MONITOR_STATES) await this.monitorStatesAsync() diff --git a/test/completeTest.js b/test/completeTest.js index 502a512c..1feedc7e 100644 --- a/test/completeTest.js +++ b/test/completeTest.js @@ -182,7 +182,7 @@ describe('complete', function () { await boss.complete(job.id) - const stateJobCount = await helper.countJobs(config.schema, 'name = $1', [`${helper.completedJobPrefix}${queue}`]) + const stateJobCount = await helper.countJobs(config.schema, 'name = $1', [`${helper.COMPLETION_JOB_PREFIX}${queue}`]) assert.strictEqual(stateJobCount, 1) }) diff --git a/test/testHelper.js b/test/testHelper.js index 2ca8f253..e3e1e219 100644 --- a/test/testHelper.js +++ b/test/testHelper.js @@ -1,6 +1,7 @@ const Db = require('../src/db') const PgBoss = require('../') const plans = require('../src/plans') +const { COMPLETION_JOB_PREFIX } = plans const crypto = require('crypto') const sha1 = (value) => crypto.createHash('sha1').update(value).digest('hex') @@ -12,7 +13,7 @@ module.exports = { getJobById, getArchivedJobById, countJobs, - completedJobPrefix: plans.completedJobPrefix, + COMPLETION_JOB_PREFIX, getConfig, getConnectionString, tryDropDb, From 26c3384b6b4da141efade357abf32837b29cacae Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Mon, 3 May 2021 14:59:32 -0500 Subject: [PATCH 09/19] schema migration and test updates --- .travis.yml | 2 +- CHANGELOG.md | 29 + package-lock.json | 3840 ++++++++++++++++++++--------------------- package.json | 4 +- src/attorney.js | 7 +- src/contractor.js | 7 +- src/manager.js | 47 +- src/migrationStore.js | 19 + src/plans.js | 48 +- test/cancelTest.js | 2 +- test/completeTest.js | 58 +- test/configTest.js | 6 +- test/expireTest.js | 11 +- test/failureTest.js | 12 +- test/subscribeTest.js | 51 +- test/testHelper.js | 7 +- version.json | 2 +- 17 files changed, 2124 insertions(+), 2028 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc0afb6f..06b51f63 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,9 @@ services: - postgresql language: node_js node_js: + - "16" - "14" - "12" - - "10" before_script: - psql -c 'create database pgboss' -U postgres - psql -c 'create extension pgcrypto' -d pgboss -U postgres diff --git a/CHANGELOG.md b/CHANGELOG.md index 050a7a17..1238ff7b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changes +## 6.0.0 :tada: + +- `stop({ graceful = true, timeout = 30000 })` will now attempt to gracefully stop any polling subscriptions (workers) by sending them a signal and then waiting for the workers to drain. The promise will still resolve once the signal is sent, so if you need to be notified when all work is completed, add a listener to the `stopped` event. Once this event is emitted, if pg-boss had created its own connection pool, it will be closed. +- Added a `wip` event for polling subscriptions that will emit as jobs are in-flight. If no work is being done, no events will be emitted. This will emit at most once every 2 seconds for monitoring purposes. +- Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. +- `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. +- Added new option, `ignoreActive`, to `publishOnce()` to ignore active jobs. +- MAJOR: Added a new index to the primary job table to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` bootstrapping promise resolution. If this is a concern, you can fetch the new schema version via `getMigrationPlans()` and create the indexes out of band. The migration includes an `IF NOT EXISTS` to bypass creation. + + For example, once you have installed this version, using the node repl, the following command will dump the migration commands for the default schema 'pgboss' (change this if customized). + + ```js + console.log(require('./node_modules/pg-boss').getMigrationPlans()) + ``` + + Which will print the indexes within the standard transaction scope: + + ```shell + BEGIN; + ... + CREATE INDEX ... + ... + COMMIT; + ``` + +- MAJOR: `onComplete` is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. +- MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. +- MAJOR: Node 10 is End-of-Life. Node 12 is now the minimum supported version. + ## 5.2.3 - Dependency PR from dependabot diff --git a/package-lock.json b/package-lock.json index 0949dcff..377e7e25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "pg-boss", - "version": "5.2.3", + "version": "6.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "5.2.3", + "version": "6.0.0", "license": "MIT", "dependencies": { "cron-parser": "^3.3.0", @@ -23,191 +23,282 @@ "standard": "^16.0.3" }, "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "dependencies": { - "@babel/highlight": "^7.10.1" + "@babel/highlight": "^7.12.13" } }, + "node_modules/@babel/compat-data": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz", + "integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==", + "dev": true + }, "node_modules/@babel/core": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", - "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.2", - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helpers": "^7.10.1", - "@babel/parser": "^7.10.2", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.2", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.0.tgz", + "integrity": "sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.14.0", + "@babel/helper-compilation-targets": "^7.13.16", + "@babel/helper-module-transforms": "^7.14.0", + "@babel/helpers": "^7.14.0", + "@babel/parser": "^7.14.0", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" }, "engines": { "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "node_modules/@babel/generator": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.0.tgz", + "integrity": "sha512-C6u00HbmsrNPug6A+CiNl8rEys7TsdcXwg12BHi2ca5rUfAs3+UwZsuDQSXnc+wCElCXMB8gMaJ3YXDdh8fAlg==", "dev": true, "dependencies": { - "ms": "^2.1.1" + "@babel/types": "^7.14.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" } }, - "node_modules/@babel/generator": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", - "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", + "integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==", "dev": true, "dependencies": { - "@babel/types": "^7.10.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" + "@babel/compat-data": "^7.13.15", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", - "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", "dev": true, "dependencies": { - "@babel/helper-get-function-arity": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" } }, "node_modules/@babel/helper-get-function-arity": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", - "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", "dev": true, "dependencies": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", - "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", "dev": true, "dependencies": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", - "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", "dev": true, "dependencies": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", - "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz", + "integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==", "dev": true, "dependencies": { - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-simple-access": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.14.0", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0" } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", - "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", "dev": true, "dependencies": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", - "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", "dev": true, "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-member-expression-to-functions": "^7.13.12", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", - "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", "dev": true, "dependencies": { - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", - "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "dev": true, "dependencies": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", "dev": true }, "node_modules/@babel/helpers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", - "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", + "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", "dev": true, "dependencies": { - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0" } }, "node_modules/@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.10.1", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", - "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.0.tgz", + "integrity": "sha512-AHbfoxesfBALg33idaTBVUkLnfXtsgvJREf93p4p0Lwsz4ppfE7g1tpEXVm4vrxUcH4DVhAa9Z1m1zqf9WUC7Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -217,50 +308,39 @@ } }, "node_modules/@babel/template": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", - "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" } }, "node_modules/@babel/traverse": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", - "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", + "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.1", - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1", + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.14.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.14.0", + "@babel/types": "^7.14.0", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" + "globals": "^11.1.0" } }, "node_modules/@babel/types": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", - "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.0.tgz", + "integrity": "sha512-O2LVLdcnWplaGxiPBz12d0HcdN8QdxdsWYhz5LSeuukV/5mn2xUUc3gBeU4QBYPJ18g/UToe8F532XJ608prmg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.10.1", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.14.0", "to-fast-properties": "^2.0.0" } }, @@ -285,18 +365,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -307,6 +375,9 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@istanbuljs/load-nyc-config": { @@ -350,6 +421,21 @@ "node": ">=8" } }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -362,30 +448,15 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { "node": ">=8" } }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -414,7 +485,10 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, "node_modules/aggregate-error": { "version": "3.1.0", @@ -429,15 +503,19 @@ } }, "node_modules/ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-colors": { @@ -450,30 +528,33 @@ } }, "node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -511,19 +592,22 @@ } }, "node_modules/array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array.prototype.flat": { @@ -538,6 +622,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array.prototype.flatmap": { @@ -553,6 +640,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/asn1": { @@ -598,15 +688,15 @@ } }, "node_modules/aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/bcrypt-pbkdf": { @@ -655,6 +745,29 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, "node_modules/buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -685,6 +798,9 @@ "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/callsites": { @@ -705,6 +821,12 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001219", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001219.tgz", + "integrity": "sha512-c0yixVG4v9KBc/tQ2rlbB3A/bgBFRvl8h8M4IeUbqCca4gsiCfvtaheUssbnux/Mb66Vjz7x8yYjDgYcNQOhyQ==", + "dev": true + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -712,29 +834,31 @@ "dev": true }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/chokidar": { @@ -777,15 +901,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/cliui/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -815,31 +930,28 @@ "node": ">=8" } }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, "node_modules/combined-stream": { @@ -884,12 +996,6 @@ "safe-buffer": "~5.1.1" } }, - "node_modules/convert-source-map/node_modules/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 - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -915,19 +1021,13 @@ "node": ">=6" } }, - "node_modules/coveralls/node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, "node_modules/cron-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.3.0.tgz", - "integrity": "sha512-Tz5WxSrDVhR7YVuLuUxhXoMGHCWoe8I7g8APkyRZNaINXHQ3zcfK97av6hBYy9ue4sOLI7ZH7SeQqi/t4jR+5A==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", + "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", "dependencies": { - "is-nan": "^1.3.0", - "luxon": "^1.25.0" + "is-nan": "^1.3.2", + "luxon": "^1.26.0" }, "engines": { "node": ">=0.8" @@ -947,21 +1047,6 @@ "node": ">= 8" } }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -975,15 +1060,20 @@ } }, "node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/debug/node_modules/ms": { @@ -1036,6 +1126,9 @@ "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/delayed-stream": { @@ -1078,6 +1171,12 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/electron-to-chromium": { + "version": "1.3.725", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.725.tgz", + "integrity": "sha512-2BbeAESz7kc6KBzs7WVrMc1BY5waUphk4D4DX5dSQXJhsc3tP5ZFaiyuL0AB7vUKzDYpIeYwTYlEfxyjsGUrhw==", + "dev": true + }, "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -1106,26 +1205,33 @@ } }, "node_modules/es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/es-to-primitive": { @@ -1140,6 +1246,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/es6-error": { @@ -1158,12 +1267,15 @@ } }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { @@ -1215,19 +1327,60 @@ }, "engines": { "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-standard": { "version": "16.0.2", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1" + } }, "node_modules/eslint-config-standard-jsx": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-10.0.0.tgz", "integrity": "sha512-hLeA2f5e06W1xyr/93/QJulN/rLbUVUmqTlexv9PRKHFwEC9ffJcH2LvJhMoEqYQBEYafedgGZXH2W8NUpt5lA==", - "dev": true + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-react": "^7.21.5" + } }, "node_modules/eslint-import-resolver-node": { "version": "0.3.4", @@ -1340,6 +1493,15 @@ "node": ">=4" } }, + "node_modules/eslint-module-utils/node_modules/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, + "engines": { + "node": ">=4" + } + }, "node_modules/eslint-module-utils/node_modules/pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -1363,6 +1525,12 @@ }, "engines": { "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" } }, "node_modules/eslint-plugin-import": { @@ -1387,6 +1555,9 @@ }, "engines": { "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -1432,6 +1603,9 @@ }, "engines": { "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" } }, "node_modules/eslint-plugin-node/node_modules/ignore": { @@ -1443,15 +1617,6 @@ "node": ">= 4" } }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-promise": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", @@ -1481,6 +1646,9 @@ }, "engines": { "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7" } }, "node_modules/eslint-plugin-react/node_modules/doctrine": { @@ -1495,16 +1663,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -1528,6 +1686,9 @@ }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { @@ -1548,58 +1709,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/eslint/node_modules/globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -1610,12 +1719,15 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1627,18 +1739,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -1676,9 +1776,9 @@ } }, "node_modules/esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -1751,9 +1851,9 @@ ] }, "node_modules/fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "node_modules/fast-json-stable-stringify": { @@ -1804,18 +1904,25 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -1896,10 +2003,24 @@ } }, "node_modules/fromentries": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", - "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", - "dev": true + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -1912,6 +2033,7 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "optional": true, "os": [ "darwin" @@ -1932,9 +2054,9 @@ "dev": true }, "node_modules/gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1950,13 +2072,16 @@ } }, "node_modules/get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-package-type": { @@ -1975,6 +2100,9 @@ "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/getpass": { @@ -1987,9 +2115,9 @@ } }, "node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -2001,12 +2129,15 @@ }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" @@ -2025,9 +2156,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "node_modules/growl": { @@ -2049,12 +2180,13 @@ } }, "node_modules/har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", "dev": true, "dependencies": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" }, "engines": { @@ -2072,27 +2204,39 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "dependencies": { "is-stream": "^2.0.0", @@ -2100,6 +2244,9 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/he": { @@ -2112,9 +2259,9 @@ } }, "node_modules/hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/html-escaper": { @@ -2158,6 +2305,9 @@ }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-fresh/node_modules/resolve-from": { @@ -2202,36 +2352,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "dependencies": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/internal-slot/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.0", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -2243,6 +2371,15 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "node_modules/is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2255,22 +2392,43 @@ "node": ">=8" } }, + "node_modules/is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", + "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", "dev": true, "dependencies": { "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { @@ -2280,6 +2438,9 @@ "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { @@ -2322,6 +2483,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-negative-zero": { @@ -2331,6 +2495,9 @@ "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-number": { @@ -2342,6 +2509,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2352,15 +2531,19 @@ } }, "node_modules/is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "dependencies": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-stream": { @@ -2379,6 +2562,9 @@ "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-symbol": { @@ -2391,6 +2577,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-typedarray": { @@ -2462,15 +2651,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", @@ -2524,19 +2704,10 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" @@ -2559,15 +2730,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2597,9 +2759,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", @@ -2658,9 +2820,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "dependencies": { "minimist": "^1.2.5" @@ -2747,22 +2909,24 @@ } }, "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.debounce": { @@ -2797,49 +2961,6 @@ "node": ">=10" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2882,33 +3003,27 @@ }, "engines": { "node": ">=8" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "dev": true, "dependencies": { - "mime-db": "1.44.0" + "mime-db": "1.47.0" }, "engines": { "node": ">= 0.6" @@ -2982,6 +3097,10 @@ }, "engines": { "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/node_modules/argparse": { @@ -2990,72 +3109,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/js-yaml": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", @@ -3068,75 +3121,12 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { + "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, "node_modules/nanoid": { "version": "3.1.20", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", @@ -3167,6 +3157,12 @@ "node": ">=8" } }, + "node_modules/node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -3179,6 +3175,15 @@ "validate-npm-package-license": "^3.0.1" } }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3229,28 +3234,6 @@ "node": ">=8.9" } }, - "node_modules/nyc/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -3262,24 +3245,6 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/nyc/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/nyc/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/nyc/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3299,23 +3264,6 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/nyc/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3337,6 +3285,21 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/nyc/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -3361,19 +3324,10 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -3384,18 +3338,6 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -3411,15 +3353,15 @@ } }, "node_modules/nyc/node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "node_modules/nyc/node_modules/yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { "cliui": "^6.0.0", @@ -3432,7 +3374,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" }, "engines": { "node": ">=8" @@ -3470,10 +3412,13 @@ } }, "node_modules/object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", + "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/object-keys": { "version": "1.1.1", @@ -3496,6 +3441,9 @@ }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.entries": { @@ -3514,33 +3462,39 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { @@ -3570,27 +3524,33 @@ } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { @@ -3602,6 +3562,9 @@ }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -3658,12 +3621,12 @@ } }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/path-is-absolute": { @@ -3709,26 +3672,34 @@ "dev": true }, "node_modules/pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.2", - "pg-protocol": "^1.4.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, "engines": { "node": ">= 8.0.0" + }, + "peerDependencies": { + "pg-native": ">=2.0.0" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } } }, "node_modules/pg-connection-string": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", - "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" }, "node_modules/pg-int8": { "version": "1.0.1", @@ -3739,14 +3710,17 @@ } }, "node_modules/pg-pool": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", - "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "peerDependencies": { + "pg": ">=8.0" + } }, "node_modules/pg-protocol": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", - "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" }, "node_modules/pg-types": { "version": "2.2.0", @@ -3772,12 +3746,15 @@ } }, "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", "dev": true, "engines": { "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { @@ -3802,6 +3779,18 @@ "node": ">=6" } }, + "node_modules/pkg-conf/node_modules/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, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/pkg-conf/node_modules/load-json-file": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", @@ -3818,6 +3807,46 @@ "node": ">=6" } }, + "node_modules/pkg-conf/node_modules/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, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-conf/node_modules/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, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/pkg-conf/node_modules/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -3831,6 +3860,15 @@ "node": ">=4" } }, + "node_modules/pkg-conf/node_modules/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, + "engines": { + "node": ">=4" + } + }, "node_modules/pkg-conf/node_modules/pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -3895,6 +3933,21 @@ "node": ">=8" } }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/pkg-dir/node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -3907,15 +3960,6 @@ "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", @@ -4116,6 +4160,15 @@ "node": ">=4" } }, + "node_modules/read-pkg-up/node_modules/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, + "engines": { + "node": ">=4" + } + }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -4142,38 +4195,19 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "dev": true, "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "engines": { "node": ">= 0.4" - } - }, - "node_modules/regexp.prototype.flags/node_modules/es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/regexpp": { @@ -4183,6 +4217,9 @@ "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, "node_modules/release-zalgo": { @@ -4201,6 +4238,7 @@ "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", @@ -4253,12 +4291,16 @@ "dev": true }, "node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "dependencies": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-from": { @@ -4280,12 +4322,16 @@ }, "bin": { "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "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 }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -4294,12 +4340,12 @@ "dev": true }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" } }, "node_modules/serialize-javascript": { @@ -4347,6 +4393,9 @@ "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/signal-exit": { @@ -4369,6 +4418,33 @@ "node": ">=6" } }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4395,21 +4471,6 @@ "node": ">=8" } }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -4486,6 +4547,20 @@ "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.3.tgz", "integrity": "sha512-70F7NH0hSkNXosXRltjSv6KpTAOkUkSfyu3ynyM5dtRUiLtR+yX9EGZ7RKwuGUqCJiX/cnkceVM6HTZ4JpaqDg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { "eslint": "~7.13.0", "eslint-config-standard": "16.0.2", @@ -4508,6 +4583,20 @@ "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-14.0.1.tgz", "integrity": "sha512-7FEzDwmHDOGva7r9ifOzD3BGdTbA7ujJ50afLVdW/tK14zQEptJjbFuUfn50irqdHDcTbNh0DTIoMPynMCXb0Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { "get-stdin": "^8.0.0", "minimist": "^1.2.5", @@ -4526,64 +4615,114 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "dependencies": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">=4" + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", + "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/strip-bom": { @@ -4602,27 +4741,24 @@ "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/table": { @@ -4640,41 +4776,6 @@ "node": ">=6.0.0" } }, - "node_modules/table/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4689,23 +4790,6 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4827,10 +4911,25 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "punycode": "^2.1.0" @@ -4850,9 +4949,9 @@ } }, "node_modules/v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "node_modules/validate-npm-package-license": { @@ -4894,6 +4993,22 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -4909,74 +5024,72 @@ "string-width": "^1.0.2 || 2" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5006,18 +5119,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5066,9 +5167,9 @@ } }, "node_modules/y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "engines": { "node": ">=10" @@ -5129,6 +5230,9 @@ "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yargs-unparser/node_modules/decamelize": { @@ -5138,15 +5242,9 @@ "dev": true, "engines": { "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, - "engines": { - "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yargs/node_modules/emoji-regex": { @@ -5178,18 +5276,6 @@ "node": ">=8" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5197,240 +5283,299 @@ "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } }, "dependencies": { "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", "dev": true, "requires": { - "@babel/highlight": "^7.10.1" + "@babel/highlight": "^7.12.13" } }, + "@babel/compat-data": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.0.tgz", + "integrity": "sha512-vu9V3uMM/1o5Hl5OekMUowo3FqXLJSw+s+66nt0fSWVWTtmosdzn45JHOB3cPtZoe6CTBDzvSw0RdOY85Q37+Q==", + "dev": true + }, "@babel/core": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", - "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.2", - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helpers": "^7.10.1", - "@babel/parser": "^7.10.2", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.2", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.0.tgz", + "integrity": "sha512-8YqpRig5NmIHlMLw09zMlPTvUVMILjqCOtVgu+TVNWEBvy9b5I3RRyhqnrV4hjgEK7n8P9OqvkWJAFmEL6Wwfw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.14.0", + "@babel/helper-compilation-targets": "^7.13.16", + "@babel/helper-module-transforms": "^7.14.0", + "@babel/helpers": "^7.14.0", + "@babel/parser": "^7.14.0", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", + "gensync": "^1.0.0-beta.2", "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", + "semver": "^6.3.0", "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } } }, "@babel/generator": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", - "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.0.tgz", + "integrity": "sha512-C6u00HbmsrNPug6A+CiNl8rEys7TsdcXwg12BHi2ca5rUfAs3+UwZsuDQSXnc+wCElCXMB8gMaJ3YXDdh8fAlg==", "dev": true, "requires": { - "@babel/types": "^7.10.2", + "@babel/types": "^7.14.0", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" } }, + "@babel/helper-compilation-targets": { + "version": "7.13.16", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz", + "integrity": "sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.15", + "@babel/helper-validator-option": "^7.12.17", + "browserslist": "^4.14.5", + "semver": "^6.3.0" + } + }, "@babel/helper-function-name": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", - "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz", + "integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-get-function-arity": "^7.12.13", + "@babel/template": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/helper-get-function-arity": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", - "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", + "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", "dev": true, "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", - "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", + "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", "dev": true, "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-imports": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", - "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz", + "integrity": "sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA==", "dev": true, "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "@babel/helper-module-transforms": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", - "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.0.tgz", + "integrity": "sha512-L40t9bxIuGOfpIGA3HNkJhU9qYrf4y5A5LUSw7rGMSn+pcG8dfJ0g6Zval6YJGd2nEjI7oP00fRdnhLKndx6bw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-simple-access": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.13.12", + "@babel/helper-replace-supers": "^7.13.12", + "@babel/helper-simple-access": "^7.13.12", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/helper-validator-identifier": "^7.14.0", + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0" } }, "@babel/helper-optimise-call-expression": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", - "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", + "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", "dev": true, "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "@babel/helper-replace-supers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", - "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz", + "integrity": "sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-member-expression-to-functions": "^7.13.12", + "@babel/helper-optimise-call-expression": "^7.12.13", + "@babel/traverse": "^7.13.0", + "@babel/types": "^7.13.12" } }, "@babel/helper-simple-access": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", - "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "version": "7.13.12", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz", + "integrity": "sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA==", "dev": true, "requires": { - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/types": "^7.13.12" } }, "@babel/helper-split-export-declaration": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", - "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", + "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", "dev": true, "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.12.13" } }, "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", "dev": true }, "@babel/helpers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", - "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.0.tgz", + "integrity": "sha512-+ufuXprtQ1D1iZTO/K9+EBRn+qPWMJjZSw/S0KlFrxCw4tkrzv9grgpDHkY9MeQTjTY8i2sp7Jep8DfU6tN9Mg==", "dev": true, "requires": { - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/template": "^7.12.13", + "@babel/traverse": "^7.14.0", + "@babel/types": "^7.14.0" } }, "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.1", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/parser": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", - "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.0.tgz", + "integrity": "sha512-AHbfoxesfBALg33idaTBVUkLnfXtsgvJREf93p4p0Lwsz4ppfE7g1tpEXVm4vrxUcH4DVhAa9Z1m1zqf9WUC7Q==", "dev": true }, "@babel/template": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", - "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", + "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/code-frame": "^7.12.13", + "@babel/parser": "^7.12.13", + "@babel/types": "^7.12.13" } }, "@babel/traverse": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", - "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.0.tgz", + "integrity": "sha512-dZ/a371EE5XNhTHomvtuLTUyx6UEoJmYX+DT5zBCQN3McHemsuIaKKYqsc/fs26BEkHs/lBZy0J571LP5z9kQA==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.1", - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1", + "@babel/code-frame": "^7.12.13", + "@babel/generator": "^7.14.0", + "@babel/helper-function-name": "^7.12.13", + "@babel/helper-split-export-declaration": "^7.12.13", + "@babel/parser": "^7.14.0", + "@babel/types": "^7.14.0", "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } + "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", - "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.0.tgz", + "integrity": "sha512-O2LVLdcnWplaGxiPBz12d0HcdN8QdxdsWYhz5LSeuukV/5mn2xUUc3gBeU4QBYPJ18g/UToe8F532XJ608prmg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.14.0", "to-fast-properties": "^2.0.0" } }, @@ -5452,18 +5597,6 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -5507,6 +5640,15 @@ "p-locate": "^4.1.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -5515,25 +5657,13 @@ "requires": { "p-limit": "^2.2.0" } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true } } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@types/json5": { @@ -5558,7 +5688,8 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "dev": true, + "requires": {} }, "aggregate-error": { "version": "3.1.0", @@ -5570,9 +5701,9 @@ } }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -5588,24 +5719,24 @@ "dev": true }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -5637,15 +5768,15 @@ } }, "array-includes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", - "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "get-intrinsic": "^1.0.1", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" } }, @@ -5706,15 +5837,15 @@ "dev": true }, "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", "dev": true }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "bcrypt-pbkdf": { @@ -5757,6 +5888,19 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + } + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -5795,6 +5939,12 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001219", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001219.tgz", + "integrity": "sha512-c0yixVG4v9KBc/tQ2rlbB3A/bgBFRvl8h8M4IeUbqCca4gsiCfvtaheUssbnux/Mb66Vjz7x8yYjDgYcNQOhyQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -5802,23 +5952,22 @@ "dev": true }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "dependencies": { "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } @@ -5855,12 +6004,6 @@ "wrap-ansi": "^7.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -5883,31 +6026,28 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", "dev": true }, "combined-stream": { @@ -5944,14 +6084,6 @@ "dev": true, "requires": { "safe-buffer": "~5.1.1" - }, - "dependencies": { - "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 - } } }, "core-util-is": { @@ -5971,23 +6103,15 @@ "log-driver": "^1.2.7", "minimist": "^1.2.5", "request": "^2.88.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } } }, "cron-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.3.0.tgz", - "integrity": "sha512-Tz5WxSrDVhR7YVuLuUxhXoMGHCWoe8I7g8APkyRZNaINXHQ3zcfK97av6hBYy9ue4sOLI7ZH7SeQqi/t4jR+5A==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz", + "integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==", "requires": { - "is-nan": "^1.3.0", - "luxon": "^1.25.0" + "is-nan": "^1.3.2", + "luxon": "^1.26.0" } }, "cross-spawn": { @@ -5999,17 +6123,6 @@ "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "dashdash": { @@ -6022,9 +6135,9 @@ } }, "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { "ms": "2.1.2" @@ -6103,6 +6216,12 @@ "safer-buffer": "^2.1.0" } }, + "electron-to-chromium": { + "version": "1.3.725", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.725.tgz", + "integrity": "sha512-2BbeAESz7kc6KBzs7WVrMc1BY5waUphk4D4DX5dSQXJhsc3tP5ZFaiyuL0AB7vUKzDYpIeYwTYlEfxyjsGUrhw==", + "dev": true + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -6128,23 +6247,27 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" } }, "es-to-primitive": { @@ -6171,9 +6294,9 @@ "dev": true }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "eslint": { @@ -6218,49 +6341,9 @@ "strip-json-comments": "^3.1.0", "table": "^5.2.3", "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -6271,22 +6354,13 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, @@ -6294,13 +6368,15 @@ "version": "16.0.2", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-config-standard-jsx": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-10.0.0.tgz", "integrity": "sha512-hLeA2f5e06W1xyr/93/QJulN/rLbUVUmqTlexv9PRKHFwEC9ffJcH2LvJhMoEqYQBEYafedgGZXH2W8NUpt5lA==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.4", @@ -6397,6 +6473,12 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "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 + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -6485,12 +6567,6 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true } } }, @@ -6527,16 +6603,6 @@ "requires": { "esutils": "^2.0.2" } - }, - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } } } }, @@ -6599,9 +6665,9 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -6657,9 +6723,9 @@ "dev": true }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-json-stable-stringify": { @@ -6704,12 +6770,13 @@ } }, "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" } }, "flat": { @@ -6774,9 +6841,9 @@ } }, "fromentries": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", - "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", "dev": true }, "fs.realpath": { @@ -6804,9 +6871,9 @@ "dev": true }, "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, "get-caller-file": { @@ -6816,9 +6883,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -6847,9 +6914,9 @@ } }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -6861,9 +6928,9 @@ } }, "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" @@ -6876,9 +6943,9 @@ "dev": true }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", "dev": true }, "growl": { @@ -6894,12 +6961,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -6911,21 +6978,27 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" }, "hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "requires": { "is-stream": "^2.0.0", @@ -6939,9 +7012,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-escaper": { @@ -7012,35 +7085,14 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", "dev": true, "requires": { - "es-abstract": "^1.17.0-next.1", + "get-intrinsic": "^1.1.0", "has": "^1.0.3", - "side-channel": "^1.0.2" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "side-channel": "^1.0.4" } }, "is-arrayish": { @@ -7049,6 +7101,12 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -7058,16 +7116,25 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", + "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", "dev": true, "requires": { "has": "^1.0.3" @@ -7121,6 +7188,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -7128,11 +7201,12 @@ "dev": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -7212,14 +7286,6 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "istanbul-lib-processinfo": { @@ -7265,16 +7331,10 @@ "supports-color": "^7.1.0" }, "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -7293,15 +7353,6 @@ "source-map": "^0.6.1" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7327,9 +7378,9 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -7379,9 +7430,9 @@ "dev": true }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "dev": true, "requires": { "minimist": "^1.2.5" @@ -7446,19 +7497,18 @@ } }, "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.debounce": { @@ -7485,42 +7535,6 @@ "dev": true, "requires": { "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } } }, "loose-envify": { @@ -7553,29 +7567,21 @@ "dev": true, "requires": { "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", "dev": true }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "dev": true, "requires": { - "mime-db": "1.44.0" + "mime-db": "1.47.0" } }, "minimatch": { @@ -7641,59 +7647,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "js-yaml": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", @@ -7702,61 +7655,13 @@ "requires": { "argparse": "^2.0.1" } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "nanoid": { @@ -7780,6 +7685,12 @@ "process-on-spawn": "^1.0.0" } }, + "node-releases": { + "version": "1.1.71", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.71.tgz", + "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", + "dev": true + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -7790,6 +7701,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "normalize-path": { @@ -7833,22 +7752,6 @@ "yargs": "^15.0.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -7860,21 +7763,6 @@ "wrap-ansi": "^6.2.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7891,20 +7779,6 @@ "path-exists": "^4.0.0" } }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7920,6 +7794,15 @@ "p-locate": "^4.1.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -7938,16 +7821,10 @@ "aggregate-error": "^3.0.0" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -7955,15 +7832,6 @@ "strip-ansi": "^6.0.0" } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7976,15 +7844,15 @@ } }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -7997,7 +7865,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" } }, "yargs-parser": { @@ -8025,9 +7893,9 @@ "dev": true }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.2.tgz", + "integrity": "sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA==", "dev": true }, "object-keys": { @@ -8060,26 +7928,26 @@ } }, "object.fromentries": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.3.tgz", - "integrity": "sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", + "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, "object.values": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", - "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has": "^1.0.3" } }, @@ -8107,21 +7975,21 @@ } }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" } }, "p-map": { @@ -8174,9 +8042,9 @@ } }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -8213,23 +8081,23 @@ "dev": true }, "pg": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz", - "integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.6.0.tgz", + "integrity": "sha512-qNS9u61lqljTDFvmk/N66EeGq3n6Ujzj0FFyNMGQr6XuEv4tgNTXvJQTfJdcvGit5p5/DWPu+wj920hAJFI+QQ==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.2", - "pg-protocol": "^1.4.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" } }, "pg-connection-string": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", - "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" }, "pg-int8": { "version": "1.0.1", @@ -8237,14 +8105,15 @@ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, "pg-pool": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", - "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.3.0.tgz", + "integrity": "sha512-0O5huCql8/D6PIRFAlmccjphLYWC+JIzvUhSzXSpGaf+tjTZc4nn+Lr7mLXBbFJfvwbP0ywDv73EiaBsxn7zdg==", + "requires": {} }, "pg-protocol": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz", - "integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" }, "pg-types": { "version": "2.2.0", @@ -8267,9 +8136,9 @@ } }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", "dev": true }, "pify": { @@ -8288,6 +8157,15 @@ "load-json-file": "^5.2.0" }, "dependencies": { + "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" + } + }, "load-json-file": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", @@ -8301,6 +8179,34 @@ "type-fest": "^0.3.0" } }, + "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" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.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" + } + }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", @@ -8311,6 +8217,12 @@ "json-parse-better-errors": "^1.0.1" } }, + "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", @@ -8359,6 +8271,15 @@ "p-locate": "^4.1.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -8367,12 +8288,6 @@ "requires": { "p-limit": "^2.2.0" } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true } } }, @@ -8527,6 +8442,12 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true + }, + "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 } } }, @@ -8550,34 +8471,13 @@ } }, "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "regexpp": { @@ -8644,11 +8544,12 @@ "dev": true }, "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { + "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, @@ -8668,9 +8569,10 @@ } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "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 }, "safer-buffer": { "version": "2.1.2", @@ -8679,9 +8581,9 @@ "dev": true }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "serialize-javascript": { @@ -8740,6 +8642,32 @@ "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + } } }, "source-map": { @@ -8760,17 +8688,6 @@ "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } } }, "spdx-correct": { @@ -8870,60 +8787,85 @@ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "requires": { "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } } }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, "string.prototype.matchall": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz", - "integrity": "sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", + "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", + "es-abstract": "^1.18.0-next.2", "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.3" + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" } }, "string.prototype.trimend": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", - "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", - "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "call-bind": "^1.0.0", + "call-bind": "^1.0.2", "define-properties": "^1.1.3" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { @@ -8939,20 +8881,12 @@ "dev": true }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "has-flag": "^4.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - } } }, "table": { @@ -8965,34 +8899,6 @@ "lodash": "^4.17.14", "slice-ansi": "^2.1.0", "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } } }, "test-exclude": { @@ -9004,22 +8910,6 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "text-table": { @@ -9121,10 +9011,22 @@ "is-typedarray": "^1.0.0" } }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -9141,9 +9043,9 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { @@ -9176,6 +9078,19 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", @@ -9189,6 +9104,33 @@ "dev": true, "requires": { "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "word-wrap": { @@ -9214,36 +9156,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -9266,15 +9178,6 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, @@ -9317,9 +9220,9 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yallist": { @@ -9343,12 +9246,6 @@ "yargs-parser": "^20.2.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -9371,15 +9268,6 @@ "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, diff --git a/package.json b/package.json index 89bdd28b..6ea8a7ea 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "pg-boss", - "version": "5.2.3", + "version": "6.0.0", "description": "Queueing jobs in Node.js using PostgreSQL like a boss", "main": "./src/index.js", "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" }, "dependencies": { "cron-parser": "^3.3.0", diff --git a/src/attorney.js b/src/attorney.js index 5d05d77c..012dc88f 100644 --- a/src/attorney.js +++ b/src/attorney.js @@ -1,4 +1,5 @@ const assert = require('assert') +const { DEFAULT_SCHEMA } = require('./plans') module.exports = { getConfig, @@ -160,7 +161,7 @@ function applyDatabaseConfig (config) { assert(!/\W/.test(config.schema), `configuration assert: ${config.schema} cannot be used as a schema. Only alphanumeric characters and underscores are allowed`) } - config.schema = config.schema || 'pgboss' + config.schema = config.schema || DEFAULT_SCHEMA } function applyArchiveConfig (config) { @@ -184,7 +185,7 @@ function applyCompletionConfig (config, defaults) { if (!('onComplete' in config)) { config.onComplete = defaults ? defaults.onComplete - : true + : false } } @@ -211,7 +212,7 @@ function applyRetentionConfig (config, defaults) { ? `${config.retentionSeconds} seconds` : defaults ? defaults.keepUntil - : '30 days' + : '14 days' config.keepUntil = keepUntil } diff --git a/src/contractor.js b/src/contractor.js index 4aaf8a65..6f473d16 100644 --- a/src/contractor.js +++ b/src/contractor.js @@ -1,18 +1,19 @@ const assert = require('assert') const plans = require('./plans') +const { DEFAULT_SCHEMA } = plans const migrationStore = require('./migrationStore') const schemaVersion = require('../version.json').schema class Contractor { - static constructionPlans (schema) { + static constructionPlans (schema = DEFAULT_SCHEMA) { return plans.create(schema, schemaVersion) } - static migrationPlans (schema, version) { + static migrationPlans (schema = DEFAULT_SCHEMA, version = schemaVersion) { return migrationStore.migrate(schema, version) } - static rollbackPlans (schema, version) { + static rollbackPlans (schema = DEFAULT_SCHEMA, version = schemaVersion) { return migrationStore.rollback(schema, version) } diff --git a/src/manager.js b/src/manager.js index 252adcb1..78605943 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,6 +1,7 @@ const assert = require('assert') const EventEmitter = require('events') const pMap = require('p-map') +const delay = require('delay') const uuid = require('uuid') const debounce = require('lodash.debounce') @@ -10,8 +11,10 @@ const Worker = require('./worker') const { QUEUES: BOSS_QUEUES } = require('./boss') const HIDDEN_QUEUES = Object.values(BOSS_QUEUES) +// todo: add cron and send it queues to ignore list + const plans = require('./plans') -const { COMPLETION_JOB_PREFIX } = plans +const { COMPLETION_JOB_PREFIX, SINGLETON_QUEUE_KEY } = plans const WIP_EVENT_INTERVAL = 2000 const WIP_DEBOUNCE_OPTIONS = { leading: true, trailing: true, maxWait: WIP_EVENT_INTERVAL } @@ -56,7 +59,8 @@ class Manager extends EventEmitter { this.deleteQueue, this.deleteAllQueues, this.clearStorage, - this.getQueueSize + this.getQueueSize, + this.getJobById ] } @@ -142,13 +146,21 @@ class Manager extends EventEmitter { const fetch = () => this.fetch(name, batchSize || teamSize, { includeMetadata }) const onFetch = async (jobs) => { + const expirationRace = (promise, timeout) => Promise.race([ + promise, + delay.reject(timeout, { value: new Error('job handler timeout exceeded in subscription') }) + ]) + // Failing will fail all fetched jobs if (batchSize) { - return await Promise.all([callback(jobs)]).catch(err => this.fail(jobs.map(job => job.id), err)) + const maxMs = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein))) + + return await expirationRace(Promise.all([callback(jobs)]), maxMs) + .catch(err => this.fail(jobs.map(job => job.id), err)) } return await pMap(jobs, job => - callback(job) + expirationRace(callback(job), plans.intervalToMs(job.expirein)) .then(result => this.complete(job.id, result)) .catch(err => this.fail(job.id, err)) , { concurrency: teamConcurrency } @@ -209,7 +221,10 @@ class Manager extends EventEmitter { async publishOnce (name, data, options, key) { options = options || {} - options.singletonKey = key || name + + const { ignoreActive = false } = options + + options.singletonKey = ignoreActive ? SINGLETON_QUEUE_KEY : key || name const result = Attorney.checkPublishArgs([name, data, options], this.config) @@ -422,9 +437,27 @@ class Manager extends EventEmitter { const sql = plans.getQueueSize(this.config.schema, options) - const { rows } = await this.db.executeSql(sql, [queue]) + const result = await this.db.executeSql(sql, [queue]) + + return result ? parseFloat(result.rows[0].count) : null + } + + async getJobById (id) { + const fetchSql = plans.getJobById(this.config.schema) + const result1 = await this.db.executeSql(fetchSql, [id]) + + if (result1 && result1.rows && result1.rows.length === 1) { + return result1.rows[0] + } + + const fetchArchiveSql = plans.getArchivedJobById(this.config.schema) + const result2 = await this.db.executeSql(fetchArchiveSql, [id]) + + if (result2 && result2.rows && result2.rows.length === 1) { + return result1.rows[0] + } - return parseFloat(rows[0].count) + return null } } diff --git a/src/migrationStore.js b/src/migrationStore.js index e498ccdb..2cf04938 100644 --- a/src/migrationStore.js +++ b/src/migrationStore.js @@ -67,6 +67,25 @@ function getAll (schema, config) { const keepUntil = config ? config.keepUntil : DEFAULT_RETENTION return [ + { + release: '6.0.0', + version: 17, + previous: 16, + install: [ + `CREATE INDEX IF NOT EXISTS job_fetch ON ${schema}.job (state, name text_pattern_ops, startAfter) WHERE state < 'active'`, + `CREATE UNIQUE INDEX IF NOT EXISTS job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < 'active' AND singletonOn IS NULL AND singletonKey = '__pgboss__singleton_queue'`, + `ALTER TABLE ${schema}.job ADD output jsonb`, + `ALTER TABLE ${schema}.archive ADD output jsonb`, + `ALTER TABLE ${schema}.job ALTER COLUMN on_complete SET DEFAULT false` + ], + uninstall: [ + `DROP INDEX ${schema}.job_fetch`, + `DROP INDEX ${schema}.job_singleton_queue`, + `ALTER TABLE ${schema}.job DROP COLUMN output`, + `ALTER TABLE ${schema}.archive DROP COLUMN output`, + `ALTER TABLE ${schema}.job ALTER COLUMN on_complete SET DEFAULT true` + ] + }, { release: '5.2.0', version: 16, diff --git a/src/plans.js b/src/plans.js index 62286579..bc3105e3 100644 --- a/src/plans.js +++ b/src/plans.js @@ -1,3 +1,5 @@ +const assert = require('assert') + const states = { created: 'created', retry: 'retry', @@ -7,8 +9,8 @@ const states = { cancelled: 'cancelled', failed: 'failed' } -const assert = require('assert') +const DEFAULT_SCHEMA = 'pgboss' const COMPLETION_JOB_PREFIX = `__state__${states.completed}__` const SINGLETON_QUEUE_KEY = '__pgboss__singleton_queue' @@ -16,6 +18,20 @@ const MUTEX = 1337968055000 const MIGRATE_RACE_MESSAGE = 'division by zero' const CREATE_RACE_MESSAGE = 'already exists' +const SECOND = 1000 +const MINUTE = SECOND * 60 +const HOUR = MINUTE * 60 +const DAY = HOUR * 24 + +// source: pg.types -> postgres-interval +const INTERVAL_MAP = { + days: DAY, + hours: HOUR, + minutes: MINUTE, + seconds: SECOND, + milliseconds: 1 +} + module.exports = { create, insertVersion, @@ -43,12 +59,22 @@ module.exports = { setMaintenanceTime, getCronTime, setCronTime, - states: { ...states }, - COMPLETION_JOB_PREFIX, locked, assertMigration, + intervalToMs, + getArchivedJobById, + getJobById, + states: { ...states }, + COMPLETION_JOB_PREFIX, + SINGLETON_QUEUE_KEY, MIGRATE_RACE_MESSAGE, - CREATE_RACE_MESSAGE + CREATE_RACE_MESSAGE, + DEFAULT_SCHEMA +} + +function intervalToMs (interval) { + const ms = Object.keys(interval).reduce((total, key) => total + INTERVAL_MAP[key] * interval[key], 0) + return ms } function locked (query) { @@ -318,7 +344,7 @@ function fetchNextJob (schema) { retryCount = CASE WHEN state = '${states.retry}' THEN retryCount + 1 ELSE retryCount END FROM nextJob WHERE j.id = nextJob.id - RETURNING ${includeMetadata ? 'j.*' : 'j.id, name, data'} + RETURNING ${includeMetadata ? 'j.*' : 'j.id, name, data, expireIn'} ` } @@ -566,3 +592,15 @@ function assertMigration (schema, version) { // raises 'division by zero' if already on desired schema version return `SELECT version::int/(version::int-${version}) from ${schema}.version` } + +function getJobById (schema) { + return getJobByTableAndId(schema, 'job') +} + +function getArchivedJobById (schema) { + return getJobByTableAndId(schema, 'archive') +} + +function getJobByTableAndId (schema, table) { + return `SELECT * From ${schema}.${table} WHERE id = $1` +} diff --git a/test/cancelTest.js b/test/cancelTest.js index 370acca5..752629fd 100644 --- a/test/cancelTest.js +++ b/test/cancelTest.js @@ -21,7 +21,7 @@ describe('cancel', function () { await boss.cancel(jobId) - const job = await helper.getJobById(config.schema, jobId) + const job = await boss.getJobById(jobId) assert(job && job.state === 'cancelled') }) diff --git a/test/completeTest.js b/test/completeTest.js index 1feedc7e..b6621be7 100644 --- a/test/completeTest.js +++ b/test/completeTest.js @@ -16,7 +16,7 @@ describe('complete', function () { }) it('should complete a batch of jobs', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'complete-batch' const batchSize = 3 @@ -43,7 +43,7 @@ describe('complete', function () { }) it('onComplete should have the payload from complete() in the response object', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const jobName = 'part-of-something-important' const responsePayload = { message: 'super-important-payload', arg2: '123' } @@ -65,7 +65,7 @@ describe('complete', function () { }) it('onComplete should have the original payload in request object', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queueName = 'onCompleteRequestTest' const requestPayload = { foo: 'bar' } @@ -86,7 +86,7 @@ describe('complete', function () { }) it('onComplete should have both request and response', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const jobName = 'onCompleteFtw' const requestPayload = { token: 'trivial' } @@ -110,7 +110,7 @@ describe('complete', function () { }) it('subscribe()\'s job.done() should allow sending completion payload', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const jobName = 'complete-from-subscribe' const responsePayload = { arg1: '123' } @@ -128,7 +128,7 @@ describe('complete', function () { }) it('should unsubscribe an onComplete subscription', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const jobName = 'offComplete' @@ -155,7 +155,7 @@ describe('complete', function () { }) it('should fetch a completed job', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'fetchCompleted' const jobId = await boss.publish(queue) @@ -167,7 +167,7 @@ describe('complete', function () { }) it('should not create an extra state job after completion', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'noMoreExtraStateJobs' const config = this.test.bossConfig @@ -188,7 +188,7 @@ describe('complete', function () { }) it('should not create a completion job if opted out during publish', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'onCompleteOptOut' @@ -234,4 +234,44 @@ describe('complete', function () { assert.strictEqual(job.data.request.id, jobId) }) + + it('should store job output in job.output from complete()', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + + const queue = 'completion-data-in-job-output' + + const jobId = await boss.publish(queue, null, { onComplete: false }) + + const { id } = await boss.fetch(queue) + + assert.strictEqual(jobId, id) + + const completionData = { msg: 'i am complete' } + + await boss.complete(jobId, completionData) + + const job = await boss.getJobById(jobId) + + assert.strictEqual(job.output.msg, completionData.msg) + }) + + it('should store job error in job.output from fail()', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + + const queue = 'completion-data-in-job-output' + + const jobId = await boss.publish(queue, null, { onComplete: false }) + + const { id } = await boss.fetch(queue) + + assert.strictEqual(jobId, id) + + const completionError = new Error('i am complete') + + await boss.fail(jobId, completionError) + + const job = await boss.getJobById(jobId) + + assert.strictEqual(job.output.message, completionError.message) + }) }) diff --git a/test/configTest.js b/test/configTest.js index 0da056c1..d9a29d98 100644 --- a/test/configTest.js +++ b/test/configTest.js @@ -8,6 +8,8 @@ describe('config', function () { config.schema = 'thisisareallylongschemanamefortestingmaximumlength' + await helper.dropSchema(config.schema) + assert.strictEqual(config.schema.length, 50) const boss = this.test.boss = new PgBoss(config) @@ -15,11 +17,13 @@ describe('config', function () { await boss.start() }) - it('should not allow more than 50 characters in schema name', function () { + it('should not allow more than 50 characters in schema name', async function () { const config = this.test.bossConfig config.schema = 'thisisareallylongschemanamefortestingmaximumlengthb' + await helper.dropSchema(config.schema) + assert(config.schema.length > 50) assert.throws(() => new PgBoss(config)) diff --git a/test/expireTest.js b/test/expireTest.js index 0b09e14f..414f94b1 100644 --- a/test/expireTest.js +++ b/test/expireTest.js @@ -6,7 +6,7 @@ describe('expire', function () { const defaults = { maintenanceIntervalSeconds: 1 } it('should expire a job', async function () { - const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, onComplete: true }) const queue = 'expire' @@ -32,15 +32,16 @@ describe('expire', function () { const jobId = await boss.publish(queue) // fetch the job but don't complete it - await boss.fetch(queue) + const { id } = await boss.fetch(queue) + + assert.strictEqual(jobId, id) // this should give it enough time to expire await delay(8000) - const job = await boss.fetchCompleted(queue) + const job = await boss.getJobById(jobId) - assert.strictEqual(jobId, job.data.request.id) - assert.strictEqual('expired', job.data.state) + assert.strictEqual('expired', job.state) }) it('should warn with an old expireIn option only once', async function () { diff --git a/test/failureTest.js b/test/failureTest.js index 16e21980..6ad797d5 100644 --- a/test/failureTest.js +++ b/test/failureTest.js @@ -30,7 +30,7 @@ describe('failure', function () { const boss = this.test.boss = await helper.start(this.test.bossConfig) const queue = 'subscribe-fail' - const jobId = await boss.publish(queue) + const jobId = await boss.publish(queue, null, { onComplete: true }) const job = await boss.fetch(queue) @@ -67,7 +67,7 @@ describe('failure', function () { const queue = 'fail-payload' const failPayload = { someReason: 'nuna' } - const jobId = await boss.publish(queue) + const jobId = await boss.publish(queue, null, { onComplete: true }) await boss.fail(jobId, failPayload) @@ -83,7 +83,7 @@ describe('failure', function () { const queue = 'fetchFailureWithPayload' const errorMessage = 'mah error' - await boss.publish(queue) + await boss.publish(queue, null, { onComplete: true }) return new Promise((resolve) => { boss.subscribe(queue, async job => { @@ -108,7 +108,7 @@ describe('failure', function () { const failPayload = 'mah error' await boss.subscribe(queue, job => Promise.reject(failPayload)) - await boss.publish(queue) + await boss.publish(queue, null, { onComplete: true }) await delay(7000) @@ -128,7 +128,7 @@ describe('failure', function () { errorResponse.something = something await boss.subscribe(queue, job => Promise.reject(errorResponse)) - await boss.publish(queue) + await boss.publish(queue, null, { onComplete: true }) await delay(7000) @@ -144,7 +144,7 @@ describe('failure', function () { const queue = 'failWithErrorObj' const message = 'a real error!' - await boss.publish(queue) + await boss.publish(queue, null, { onComplete: true }) await boss.subscribe(queue, async () => { throw new Error(message) }) await delay(2000) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index 1a35b7b3..03b1a241 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -193,7 +193,7 @@ describe('subscribe', function () { }) it('subscribe completion should pass string wrapped in value prop', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'subscribeCompletionString' const result = 'success' @@ -211,7 +211,7 @@ describe('subscribe', function () { }) it('subscribe completion via Promise resolve() should pass object payload', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) const queue = 'subscribeCompletionObject' const something = 'clever' @@ -250,4 +250,51 @@ describe('subscribe', function () { }) }) }) + + it('should fail job at expiration without maintenance', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + + const queue = this.test.bossConfig.schema + + const maintenanceTick = new Promise((resolve) => boss.on('maintenance', resolve)) + + await maintenanceTick + + const jobId = await boss.publish(queue, null, { expireInSeconds: 1 }) + + await boss.subscribe(queue, () => delay(2000)) + + await delay(2000) + + const job = await boss.getJobById(jobId) + + assert.strictEqual(job.state, 'failed') + assert(job.output.message.includes('timeout')) + }) + + it('should fail a batch of jobs at expiration without maintenance', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + + const queue = this.test.bossConfig.schema + + const maintenanceTick = new Promise((resolve) => boss.on('maintenance', resolve)) + + await maintenanceTick + + const jobId1 = await boss.publish(queue, null, { expireInSeconds: 1 }) + const jobId2 = await boss.publish(queue, null, { expireInSeconds: 1 }) + + await boss.subscribe(queue, { batchSize: 2 }, () => delay(2000)) + + await delay(2000) + + const job1 = await boss.getJobById(jobId1) + const job2 = await boss.getJobById(jobId2) + + assert.strictEqual(job1.state, 'failed') + assert(job1.output.message, 'job handler timeout exceeded in subscription') + + assert.strictEqual(job2.state, 'failed') + assert(job2.output.message, 'job handler timeout exceeded in subscription') + }) }) diff --git a/test/testHelper.js b/test/testHelper.js index e3e1e219..727246ea 100644 --- a/test/testHelper.js +++ b/test/testHelper.js @@ -10,9 +10,9 @@ module.exports = { start, stop, getDb, - getJobById, getArchivedJobById, countJobs, + findJobs, COMPLETION_JOB_PREFIX, getConfig, getConnectionString, @@ -64,11 +64,6 @@ async function dropSchema (schema) { await db.close() } -async function getJobById (schema, id) { - const response = await findJobs(schema, 'id = $1', [id]) - return response.rows.length ? response.rows[0] : null -} - async function findJobs (schema, where, values) { const db = await getDb() const jobs = await db.executeSql(`select * from ${schema}.job where ${where}`, values) diff --git a/version.json b/version.json index 9e9e6673..ff110cc8 100644 --- a/version.json +++ b/version.json @@ -1,3 +1,3 @@ { - "schema": 16 + "schema": 17 } From 64f60f92f704dacae8c456137857f7d161192c4a Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Mon, 3 May 2021 16:12:40 -0500 Subject: [PATCH 10/19] tests and db close race condition --- src/db.js | 2 +- src/plans.js | 4 ++-- test/subscribeTest.js | 17 +++++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/db.js b/src/db.js index 7094092e..5dc178ea 100644 --- a/src/db.js +++ b/src/db.js @@ -18,8 +18,8 @@ class Db extends EventEmitter { async close () { if (!this.pool.ending) { - await this.pool.end() this.opened = false + await this.pool.end() } } diff --git a/src/plans.js b/src/plans.js index bc3105e3..8fcb67b2 100644 --- a/src/plans.js +++ b/src/plans.js @@ -24,7 +24,7 @@ const HOUR = MINUTE * 60 const DAY = HOUR * 24 // source: pg.types -> postgres-interval -const INTERVAL_MAP = { +const INTERVAL_TO_MS_MAP = { days: DAY, hours: HOUR, minutes: MINUTE, @@ -73,7 +73,7 @@ module.exports = { } function intervalToMs (interval) { - const ms = Object.keys(interval).reduce((total, key) => total + INTERVAL_MAP[key] * interval[key], 0) + const ms = Object.keys(interval).reduce((total, key) => total + INTERVAL_TO_MS_MAP[key] * interval[key], 0) return ms } diff --git a/test/subscribeTest.js b/test/subscribeTest.js index 03b1a241..11e825e3 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -1,6 +1,7 @@ const delay = require('delay') const assert = require('assert') const helper = require('./testHelper') +const PgBoss = require('../') describe('subscribe', function () { it('should fail with no arguments', async function () { @@ -252,14 +253,18 @@ describe('subscribe', function () { }) it('should fail job at expiration without maintenance', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = new PgBoss(this.test.bossConfig) - const queue = this.test.bossConfig.schema + boss.on('error', err => console.log(err)) const maintenanceTick = new Promise((resolve) => boss.on('maintenance', resolve)) + await boss.start() + await maintenanceTick + const queue = this.test.bossConfig.schema + const jobId = await boss.publish(queue, null, { expireInSeconds: 1 }) await boss.subscribe(queue, () => delay(2000)) @@ -273,14 +278,18 @@ describe('subscribe', function () { }) it('should fail a batch of jobs at expiration without maintenance', async function () { - const boss = this.test.boss = await helper.start(this.test.bossConfig) + const boss = this.test.boss = new PgBoss(this.test.bossConfig) - const queue = this.test.bossConfig.schema + boss.on('error', err => console.log(err)) const maintenanceTick = new Promise((resolve) => boss.on('maintenance', resolve)) + await boss.start() + await maintenanceTick + const queue = this.test.bossConfig.schema + const jobId1 = await boss.publish(queue, null, { expireInSeconds: 1 }) const jobId2 = await boss.publish(queue, null, { expireInSeconds: 1 }) From 912a89df581c917439efb5fe82c2416d4de82cf7 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 4 May 2021 00:12:19 -0500 Subject: [PATCH 11/19] test fixes and docs --- CHANGELOG.md | 34 +++++++++++++++++----------------- docs/images/job-states.png | Bin 55393 -> 47805 bytes docs/usage.md | 9 ++++++++- src/contractor.js | 2 +- src/manager.js | 15 ++++++++++++--- src/migrationStore.js | 4 ++++ src/plans.js | 16 ++++++++-------- test/archiveTest.js | 20 ++++++++++++++++++++ test/singletonTest.js | 30 ++++++++++++++++++++++++++++++ 9 files changed, 100 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1238ff7b..8260271c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,33 +2,33 @@ ## 6.0.0 :tada: -- `stop({ graceful = true, timeout = 30000 })` will now attempt to gracefully stop any polling subscriptions (workers) by sending them a signal and then waiting for the workers to drain. The promise will still resolve once the signal is sent, so if you need to be notified when all work is completed, add a listener to the `stopped` event. Once this event is emitted, if pg-boss had created its own connection pool, it will be closed. -- Added a `wip` event for polling subscriptions that will emit as jobs are in-flight. If no work is being done, no events will be emitted. This will emit at most once every 2 seconds for monitoring purposes. -- Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. -- `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. -- Added new option, `ignoreActive`, to `publishOnce()` to ignore active jobs. -- MAJOR: Added a new index to the primary job table to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` bootstrapping promise resolution. If this is a concern, you can fetch the new schema version via `getMigrationPlans()` and create the indexes out of band. The migration includes an `IF NOT EXISTS` to bypass creation. +- CHANGE: `stop()` has been enhanced with a **graceful stop** feature that will signal and monitor any polling subscriptions (workers using `subscribe()` or `onComlete()`) before closing the internal connection pool and stopping maintenance operations. The defalt options, `{ graceful = true, timeout = 30000 }`, will wait up to 30s before shutting down. +- NEW: Added a `stopped` event that will be emitted after `stop()` when all workers have completed active jobs, or when the timeout is met, whichever is sooner. +- NEW: Added a `wip` event that will emit as jobs are both fetched and completed. If no work is being done, no events will be emitted. This will emit at most once every 2 seconds for monitoring purposes. +- NEW: Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. +- NEW: `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. +- NEW: Added new function, `publishSingleton()`, similar to publishOnce(), but throttles publish to only allow 1 job in the queue at a time, allowing a job to be queued even if 1 or more jobs are currently active. +- MAJOR: `onComplete` is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. +- MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. +- MAJOR: Node 10 is EOL. Node 12 is now the minimum supported version. +- MAJOR: Added a new index to the primary job table to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` promise resolution. If this is a concern, you can fetch the new schema version via `getMigrationPlans()` and create the indexes out of band. The migration includes an `IF NOT EXISTS` to bypass creation. - For example, once you have installed this version, using the node repl, the following command will dump the migration commands for the default schema 'pgboss' (change this if customized). + In the following example, once you have installed this package version, using the node repl, you can get the DDL for the index from `getMigrationPlans()`. - ```js - console.log(require('./node_modules/pg-boss').getMigrationPlans()) - ``` + ```shell - Which will print the indexes within the standard transaction scope: + $ node + Welcome to Node.js v14.16.1. + Type ".help" for more information. + > console.log(require('./node_modules/pg-boss').getMigrationPlans()) - ```shell BEGIN; ... - CREATE INDEX ... + CREATE INDEX IF NOT EXISTS job_fetch ... ... COMMIT; ``` -- MAJOR: `onComplete` is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. -- MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. -- MAJOR: Node 10 is End-of-Life. Node 12 is now the minimum supported version. - ## 5.2.3 - Dependency PR from dependabot diff --git a/docs/images/job-states.png b/docs/images/job-states.png index 4654da7a5336c708916ec04f4e4cef07897a203c..a62b9347c19e256ef6ac9aa105c0215e8cb2eaa9 100644 GIT binary patch literal 47805 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

iUyN*Ri{Ul(g2%n{ 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 z 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 ZV@ao%M(evjLGq)pvHZ*8xVgvb{{tcsLJa@_ literal 55393 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

CqKbECmCBM0DbOS3`<-s%j5#1=)qa3F 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 diff --git a/docs/usage.md b/docs/usage.md index b7a9f37c..f356f5aa 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -25,6 +25,7 @@ - [`publish(request)`](#publishrequest) - [`publishAfter(name, data, options, seconds | ISO date string | Date)`](#publishaftername-data-options-seconds--iso-date-string--date) - [`publishOnce(name, data, options, key)`](#publishoncename-data-options-key) + - [`publishSingleton(name, data, options)`](#publishsingletonname-data-options) - [`publishThrottled(name, data, options, seconds [, key])`](#publishthrottledname-data-options-seconds--key) - [`publishDebounced(name, data, options, seconds [, key])`](#publishdebouncedname-data-options-seconds--key) - [`subscribe()`](#subscribe) @@ -332,7 +333,13 @@ This is a convenience version of `publish()` with the `startAfter` option assign ### `publishOnce(name, data, options, key)` -Publish a job with a unique key to make sure it isn't processed more than once. Any other jobs published during this archive interval with the same queue name and key will be rejected. +Publish a job with a unique key to only allow 1 job to be in created, retry, or active state at a time. + +This is a convenience version of `publish()` with the `singletonKey` option assigned. + +### `publishSingleton(name, data, options)` + +Publish a job but only allow 1 job to be in created or retry state at at time. This is a convenience version of `publish()` with the `singletonKey` option assigned. diff --git a/src/contractor.js b/src/contractor.js index 6f473d16..a77bad9b 100644 --- a/src/contractor.js +++ b/src/contractor.js @@ -9,7 +9,7 @@ class Contractor { return plans.create(schema, schemaVersion) } - static migrationPlans (schema = DEFAULT_SCHEMA, version = schemaVersion) { + static migrationPlans (schema = DEFAULT_SCHEMA, version = schemaVersion - 1) { return migrationStore.migrate(schema, version) } diff --git a/src/manager.js b/src/manager.js index 78605943..1aabf4b5 100644 --- a/src/manager.js +++ b/src/manager.js @@ -56,6 +56,7 @@ class Manager extends EventEmitter { this.publishThrottled, this.publishOnce, this.publishAfter, + this.publishSingleton, this.deleteQueue, this.deleteAllQueues, this.clearStorage, @@ -222,9 +223,17 @@ class Manager extends EventEmitter { async publishOnce (name, data, options, key) { options = options || {} - const { ignoreActive = false } = options + options.singletonKey = key || name - options.singletonKey = ignoreActive ? SINGLETON_QUEUE_KEY : key || name + const result = Attorney.checkPublishArgs([name, data, options], this.config) + + return this.createJob(result.name, result.data, result.options) + } + + async publishSingleton (name, data, options) { + options = options || {} + + options.singletonKey = SINGLETON_QUEUE_KEY const result = Attorney.checkPublishArgs([name, data, options], this.config) @@ -454,7 +463,7 @@ class Manager extends EventEmitter { const result2 = await this.db.executeSql(fetchArchiveSql, [id]) if (result2 && result2.rows && result2.rows.length === 1) { - return result1.rows[0] + return result2.rows[0] } return null diff --git a/src/migrationStore.js b/src/migrationStore.js index 2cf04938..4f11122c 100644 --- a/src/migrationStore.js +++ b/src/migrationStore.js @@ -74,6 +74,8 @@ function getAll (schema, config) { install: [ `CREATE INDEX IF NOT EXISTS job_fetch ON ${schema}.job (state, name text_pattern_ops, startAfter) WHERE state < 'active'`, `CREATE UNIQUE INDEX IF NOT EXISTS job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < 'active' AND singletonOn IS NULL AND singletonKey = '__pgboss__singleton_queue'`, + `DROP INDEX ${schema}.job_singletonKey`, + `CREATE UNIQUE INDEX job_singletonKey ON ${schema}.job (name, singletonKey) WHERE state < 'completed' AND singletonOn IS NULL AND NOT singletonKey = '__pgboss__singleton_queue'`, `ALTER TABLE ${schema}.job ADD output jsonb`, `ALTER TABLE ${schema}.archive ADD output jsonb`, `ALTER TABLE ${schema}.job ALTER COLUMN on_complete SET DEFAULT false` @@ -81,6 +83,8 @@ function getAll (schema, config) { uninstall: [ `DROP INDEX ${schema}.job_fetch`, `DROP INDEX ${schema}.job_singleton_queue`, + `DROP INDEX ${schema}.job_singletonKey`, + `CREATE UNIQUE INDEX job_singletonKey ON ${schema}.job (name, singletonKey) WHERE state < 'completed' AND singletonOn IS NULL`, `ALTER TABLE ${schema}.job DROP COLUMN output`, `ALTER TABLE ${schema}.archive DROP COLUMN output`, `ALTER TABLE ${schema}.job ALTER COLUMN on_complete SET DEFAULT true` diff --git a/src/plans.js b/src/plans.js index 8fcb67b2..23ca63ad 100644 --- a/src/plans.js +++ b/src/plans.js @@ -229,7 +229,14 @@ function getQueueSize (schema, options = {}) { function createIndexSingletonKey (schema) { // anything with singletonKey means "only 1 job can be queued or active at a time" return ` - CREATE UNIQUE INDEX job_singletonKey ON ${schema}.job (name, singletonKey) WHERE state < '${states.completed}' AND singletonOn IS NULL + CREATE UNIQUE INDEX job_singletonKey ON ${schema}.job (name, singletonKey) WHERE state < '${states.completed}' AND singletonOn IS NULL AND NOT singletonKey = '${SINGLETON_QUEUE_KEY}' + ` +} + +function createIndexSingletonQueue (schema) { + // "singleton queue" means "only 1 job can be queued at a time" + return ` + CREATE UNIQUE INDEX job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < '${states.active}' AND singletonOn IS NULL AND singletonKey = '${SINGLETON_QUEUE_KEY}' ` } @@ -247,13 +254,6 @@ function createIndexSingletonKeyOn (schema) { ` } -function createIndexSingletonQueue (schema) { - // "singleton queue" means "only 1 job can be queued at a time" - return ` - CREATE UNIQUE INDEX job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < '${states.active}' AND singletonOn IS NULL AND singletonKey = '${SINGLETON_QUEUE_KEY}' - ` -} - function createIndexJobName (schema) { return ` CREATE INDEX job_name ON ${schema}.job (name text_pattern_ops) diff --git a/test/archiveTest.js b/test/archiveTest.js index 765e3d67..cfe9a6c5 100644 --- a/test/archiveTest.js +++ b/test/archiveTest.js @@ -29,6 +29,26 @@ describe('archive', function () { assert.strictEqual(queue, archivedJob.name) }) + it('should retrieve an archived job via getJobById()', async function () { + const config = { ...this.test.bossConfig, ...defaults } + const boss = this.test.boss = await helper.start(config) + const queue = this.test.bossConfig.schema + + const jobId = await boss.publish(queue) + const job = await boss.fetch(queue) + + assert.strictEqual(job.id, jobId) + + await boss.complete(jobId) + + await delay(4000) + + const archivedJob = await boss.getJobById(jobId) + + assert.strictEqual(jobId, archivedJob.id) + assert.strictEqual(queue, archivedJob.name) + }) + it('should archive a created job', async function () { const config = { ...this.test.bossConfig, ...defaults } const boss = this.test.boss = await helper.start(config) diff --git a/test/singletonTest.js b/test/singletonTest.js index 4db94c66..cef05708 100644 --- a/test/singletonTest.js +++ b/test/singletonTest.js @@ -60,6 +60,14 @@ describe('singleton', function () { const jobId2 = await boss.publishOnce(queue, null, null, key) assert.strictEqual(jobId2, null) + + const job = await boss.fetch(queue) + + assert.strictEqual(job.id, jobId) + + const jobId3 = await boss.publishOnce(queue, null, null, key) + + assert.strictEqual(jobId3, null) }) it('publishOnce() without a key should also work', async function () { @@ -74,4 +82,26 @@ describe('singleton', function () { assert.strictEqual(jobId2, null) }) + + it('publishSingleton() works', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + + const queue = this.test.bossConfig.schema + + const jobId = await boss.publishSingleton(queue) + + assert(jobId) + + const jobId2 = await boss.publishSingleton(queue) + + assert.strictEqual(jobId2, null) + + const job = await boss.fetch(queue) + + assert.strictEqual(job.id, jobId) + + const jobId3 = await boss.publishSingleton(queue) + + assert(jobId3) + }) }) From 44bf6b7a6b0aeb0300909146f8d4fcfa392de10e Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 4 May 2021 13:01:15 -0500 Subject: [PATCH 12/19] fixes and tests --- CHANGELOG.md | 4 +++- docs/usage.md | 29 ++++++++++++++++++++++- package.json | 2 +- src/manager.js | 22 +++++++++++++----- src/migrationStore.js | 4 ++-- src/plans.js | 2 +- test/databaseTest.js | 45 ------------------------------------ test/{global.js => hooks.js} | 13 +++++++---- test/subscribeTest.js | 20 ++++++++++++++++ 9 files changed, 80 insertions(+), 61 deletions(-) rename test/{global.js => hooks.js} (85%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8260271c..07b49695 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ - NEW: Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. - NEW: `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. - NEW: Added new function, `publishSingleton()`, similar to publishOnce(), but throttles publish to only allow 1 job in the queue at a time, allowing a job to be queued even if 1 or more jobs are currently active. -- MAJOR: `onComplete` is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. +- CHANGE: `subscribe()` now resolves with a unique worker id that will be visible in `wip` along with additional metadata about the subscription. +- CHANGE: `unsubscribe()` now accepts an object as an argument to allow removing a specific subscription by id. Use `{ worker: 'id' }`. +- MAJOR: The `onComplete` publish option is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. - MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. - MAJOR: Node 10 is EOL. Node 12 is now the minimum supported version. - MAJOR: Added a new index to the primary job table to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` promise resolution. If this is a concern, you can fetch the new schema version via `getMigrationPlans()` and create the indexes out of band. The migration includes an `IF NOT EXISTS` to bypass creation. diff --git a/docs/usage.md b/docs/usage.md index f356f5aa..a99847f5 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -11,6 +11,8 @@ - [Events](#events) - [`error`](#error) - [`monitor-states`](#monitor-states) + - [`wip`](#wip) + - [`stopped`](#stopped) - [Static functions](#static-functions) - [`string getConstructionPlans(schema)`](#string-getconstructionplansschema) - [`string getMigrationPlans(schema, version)`](#string-getmigrationplansschema-version) @@ -188,6 +190,31 @@ The payload of the event is an object with a key per queue and state, such as th "all": 4694 } ``` +## `wip` + +Emitted at most once every 2 seconds when polling subscriptions are active and jobs are entering or leaving active state. The payload is an array that represents each worker in this instance of pg-boss. If you want to monitor queue activity across all instances, use `monitor-states`. + +```js +[ + { + id: 'fc738fb0-1de5-4947-b138-40d6a790749e', + name: 'my-queue', + options: { newJobCheckInterval: 2000 }, + state: 'active', + count: 1, + createdOn: 1620149137015, + lastFetchedOn: 1620149137015, + lastJobStartedOn: 1620149137015, + lastJobEndedOn: null, + lastError: null, + lastErrorOn: null + } +] +``` + +## `stopped` + +Emitted after `stop()` once all subscription workers have completed their work and maintenance has been shut down. # Static functions @@ -359,7 +386,7 @@ This is a convenience version of `publish()` with the `singletonSeconds`, `singl **returns: Promise** -Polls the database by a queue name or a pattern and executes the provided callback function when jobs are found. The promise resolves once a subscription has been created. +Polls the database by a queue name or a pattern and executes the provided callback function when jobs are found. The promise resolves once a subscription has been created with a unique id of the subscription. You can monitor the state of subscriptions using the `wip` event. Queue patterns use the `*` character to match 0 or more characters. For example, a job from queue `status-report-12345` would be fetched with pattern `status-report-*` or even `stat*5`. diff --git a/package.json b/package.json index 6ea8a7ea..07dedc3b 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "standard": "^16.0.3" }, "scripts": { - "test": "standard && mocha --exit --no-warnings", + "test": "standard && mocha --exit --no-warnings --parallel --require ./test/hooks", "cover": "nyc --reporter=text npm test", "forcover": "npm run cover && nyc report --reporter=text-lcov | coveralls", "export-schema": "node ./scripts/construct.js", diff --git a/src/manager.js b/src/manager.js index 1aabf4b5..0ecaec71 100644 --- a/src/manager.js +++ b/src/manager.js @@ -63,6 +63,8 @@ class Manager extends EventEmitter { this.getQueueSize, this.getJobById ] + + this.emitWipThrottled = debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) } async stop () { @@ -129,10 +131,6 @@ class Manager extends EventEmitter { return data } - emitWipThrottled () { - debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) - } - async watch (name, options, callback) { const { newJobCheckInterval: interval = this.config.newJobCheckInterval, @@ -152,20 +150,32 @@ class Manager extends EventEmitter { delay.reject(timeout, { value: new Error('job handler timeout exceeded in subscription') }) ]) + if (!HIDDEN_QUEUES.includes(name)) { + this.emitWipThrottled() + } + + let result + // Failing will fail all fetched jobs if (batchSize) { const maxMs = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein))) - return await expirationRace(Promise.all([callback(jobs)]), maxMs) + result = await expirationRace(Promise.all([callback(jobs)]), maxMs) .catch(err => this.fail(jobs.map(job => job.id), err)) } - return await pMap(jobs, job => + result = await pMap(jobs, job => expirationRace(callback(job), plans.intervalToMs(job.expirein)) .then(result => this.complete(job.id, result)) .catch(err => this.fail(job.id, err)) , { concurrency: teamConcurrency } ).catch(() => {}) // allow promises & non-promises to live together in harmony + + if (!HIDDEN_QUEUES.includes(name)) { + this.emitWipThrottled() + } + + return result } const onError = error => { diff --git a/src/migrationStore.js b/src/migrationStore.js index 4f11122c..f8e0fbce 100644 --- a/src/migrationStore.js +++ b/src/migrationStore.js @@ -72,10 +72,10 @@ function getAll (schema, config) { version: 17, previous: 16, install: [ - `CREATE INDEX IF NOT EXISTS job_fetch ON ${schema}.job (state, name text_pattern_ops, startAfter) WHERE state < 'active'`, - `CREATE UNIQUE INDEX IF NOT EXISTS job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < 'active' AND singletonOn IS NULL AND singletonKey = '__pgboss__singleton_queue'`, `DROP INDEX ${schema}.job_singletonKey`, `CREATE UNIQUE INDEX job_singletonKey ON ${schema}.job (name, singletonKey) WHERE state < 'completed' AND singletonOn IS NULL AND NOT singletonKey = '__pgboss__singleton_queue'`, + `CREATE UNIQUE INDEX job_singleton_queue ON ${schema}.job (name, singletonKey) WHERE state < 'active' AND singletonOn IS NULL AND singletonKey = '__pgboss__singleton_queue'`, + `CREATE INDEX IF NOT EXISTS job_fetch ON ${schema}.job (name text_pattern_ops, startAfter) WHERE state < 'active'`, `ALTER TABLE ${schema}.job ADD output jsonb`, `ALTER TABLE ${schema}.archive ADD output jsonb`, `ALTER TABLE ${schema}.job ALTER COLUMN on_complete SET DEFAULT false` diff --git a/src/plans.js b/src/plans.js index 23ca63ad..bf4cb9e4 100644 --- a/src/plans.js +++ b/src/plans.js @@ -262,7 +262,7 @@ function createIndexJobName (schema) { function createIndexJobFetch (schema) { return ` - CREATE INDEX job_fetch ON ${schema}.job (state, name text_pattern_ops, startAfter) + CREATE INDEX job_fetch ON ${schema}.job (name text_pattern_ops, startAfter) WHERE state < '${states.active}' ` } diff --git a/test/databaseTest.js b/test/databaseTest.js index 75481ef3..3f4115ac 100644 --- a/test/databaseTest.js +++ b/test/databaseTest.js @@ -1,8 +1,5 @@ -const delay = require('delay') -const pMap = require('p-map') const assert = require('assert') const PgBoss = require('../') -const helper = require('./testHelper') describe('database', function () { it('should fail on invalid database host', async function () { @@ -28,46 +25,4 @@ describe('database', function () { assert(response.text === query) }) - - it('connection count does not exceed configured pool size', async function () { - this.retries(1) - - const listenerCount = 100 - const poolSize = 5 - - const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, max: poolSize }) - - const newConnections = await poolSizeConnectionTest(boss, listenerCount) - - assert(newConnections <= poolSize) - }) - - async function poolSizeConnectionTest (boss, listenerCount) { - const listeners = [] - - for (let x = 0; x < listenerCount; x++) { - listeners[x] = x - } - - const prevConnectionCount = await countConnections(boss.db) - - await pMap(listeners, (val, index) => boss.subscribe(`job${index}`, () => {})) - - await delay(3000) - - const connectionCount = await countConnections(boss.db) - - const newConnections = connectionCount - prevConnectionCount - - return newConnections - - async function countConnections (db) { - const sql = 'SELECT count(*) as connections FROM pg_stat_activity WHERE application_name=$1' - const values = [boss.db.config.application_name] - - const result = await db.executeSql(sql, values) - - return parseFloat(result.rows[0].connections) - } - } }) diff --git a/test/global.js b/test/hooks.js similarity index 85% rename from test/global.js rename to test/hooks.js index d5d14f5d..9413479f 100644 --- a/test/global.js +++ b/test/hooks.js @@ -1,14 +1,19 @@ const helper = require('./testHelper') -beforeEach(async function () { +exports.mochaHooks = { + beforeEach, + afterEach +} + +async function beforeEach () { this.timeout(2000) const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) console.log(` ${this.currentTest.title} (schema: ${config.schema})...`) await helper.dropSchema(config.schema) this.currentTest.bossConfig = config -}) +} -afterEach(async function () { +async function afterEach () { this.timeout(10000) const config = helper.getConfig({ testKey: getTestKey(this.currentTest) }) @@ -23,7 +28,7 @@ afterEach(async function () { } await helper.dropSchema(config.schema) -}) +} function getTestKey (ctx) { return ctx.file + ctx.parent.title + ctx.title diff --git a/test/subscribeTest.js b/test/subscribeTest.js index 11e825e3..4cd214ba 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -306,4 +306,24 @@ describe('subscribe', function () { assert.strictEqual(job2.state, 'failed') assert(job2.output.message, 'job handler timeout exceeded in subscription') }) + + it('should emit wip event every 2s during subscriptions', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = this.test.bossConfig.schema + + const firstWipEvent = new Promise(resolve => boss.once('wip', resolve)) + + await boss.publish(queue) + await boss.subscribe(queue, () => delay(1000)) + + const wip1 = await firstWipEvent + + assert.strictEqual(wip1.length, 1) + + const secondWipEvent = new Promise(resolve => boss.once('wip', resolve)) + + const wip2 = await secondWipEvent + + assert.strictEqual(wip2.length, 0) + }) }) From 9c1e4ff94dd4681ccffd32305a88a428d35583d0 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 4 May 2021 16:01:55 -0500 Subject: [PATCH 13/19] test and docs --- CHANGELOG.md | 5 +++-- docs/usage.md | 19 +++++++++++++------ src/db.js | 2 +- src/manager.js | 36 ++++++++++++++++++++---------------- test/completeTest.js | 26 +++++++++++++++++++++++++- test/subscribeTest.js | 19 +++++++++++++++++++ 6 files changed, 81 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07b49695..a5b111b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,9 @@ - NEW: Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. - NEW: `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. - NEW: Added new function, `publishSingleton()`, similar to publishOnce(), but throttles publish to only allow 1 job in the queue at a time, allowing a job to be queued even if 1 or more jobs are currently active. -- CHANGE: `subscribe()` now resolves with a unique worker id that will be visible in `wip` along with additional metadata about the subscription. -- CHANGE: `unsubscribe()` now accepts an object as an argument to allow removing a specific subscription by id. Use `{ worker: 'id' }`. +- CHANGE: `subscribe()` and `onComplete()` now resolve with a unique worker id that will be visible in `wip` along with additional metadata about the subscription. +- CHANGE: `subscribe()` and `onComplete()` now abort promise execution client-side based on the job's expiration. +- CHANGE: `unsubscribe()` and `offComplete()` now accept an object as an argument to allow removing a specific subscription by id. - MAJOR: The `onComplete` publish option is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. - MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. - MAJOR: Node 10 is EOL. Node 12 is now the minimum supported version. diff --git a/docs/usage.md b/docs/usage.md index a99847f5..f55dacd0 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -33,8 +33,8 @@ - [`subscribe()`](#subscribe) - [`subscribe(name [, options], handler)`](#subscribename--options-handler) - [`onComplete(name [, options], handler)`](#oncompletename--options-handler) - - [`unsubscribe(name)`](#unsubscribename) - - [`offComplete(name)`](#offcompletename) + - [`unsubscribe(value)`](#unsubscribevalue) + - [`offComplete(value)`](#offcompletevalue) - [`fetch()`](#fetch) - [`fetch(name)`](#fetchname) - [`fetch(name, batchSize, [, options])`](#fetchname-batchsize--options) @@ -495,13 +495,20 @@ The following is an example data object from the job retrieved in the onComplete } ``` -## `unsubscribe(name)` +## `unsubscribe(value)` -Removes a subscription by name and stops polling. +Removes a subscription by name or id and stops polling. -### `offComplete(name)` +** Arguments ** +- value: string or object -Same as `unsubscribe()`, but removes an `onComplete()` subscription. + If a string, removes all subscriptions found matching the name. If an object, only the subscription with a matching `id` will be removed. + +### `offComplete(value)` + +Similar to `unsubscribe()`, but removes an `onComplete()` subscription. + +** ## `fetch()` diff --git a/src/db.js b/src/db.js index 5dc178ea..d5ab1caa 100644 --- a/src/db.js +++ b/src/db.js @@ -25,7 +25,7 @@ class Db extends EventEmitter { async executeSql (text, values) { if (this.opened) { - return this.pool.query(text, values) + return await this.pool.query(text, values) } } } diff --git a/src/manager.js b/src/manager.js index 0ecaec71..f229bef4 100644 --- a/src/manager.js +++ b/src/manager.js @@ -79,12 +79,12 @@ class Manager extends EventEmitter { async subscribe (name, ...args) { const { options, callback } = Attorney.checkSubscribeArgs(name, args, this.config) - return this.watch(name, options, callback) + return await this.watch(name, options, callback) } async onComplete (name, ...args) { const { options, callback } = Attorney.checkSubscribeArgs(name, args, this.config) - return this.watch(COMPLETION_JOB_PREFIX + name, options, callback) + return await this.watch(COMPLETION_JOB_PREFIX + name, options, callback) } addWorker (worker) { @@ -195,12 +195,12 @@ class Manager extends EventEmitter { assert(value, 'Missing required argument') const query = (typeof value === 'string') - ? { type: 'name', value, filter: i => i.name === value } - : (typeof value === 'object' && value.worker) - ? { type: 'worker', value: value.worker, filter: i => i.id === value.worker } + ? { filter: i => i.name === value } + : (typeof value === 'object' && value.id) + ? { filter: i => i.id === value.id } : null - assert(query, 'Invalid argument. Expected string or object: { worker: id }') + assert(query, 'Invalid argument. Expected string or object: { id }') const workers = this.getWorkers().filter(i => query.filter(i) && !i.stopping && !i.stopped) @@ -221,13 +221,17 @@ class Manager extends EventEmitter { }, 1000) } - async offComplete (name) { - return this.unsubscribe(COMPLETION_JOB_PREFIX + name) + async offComplete (value) { + if (typeof value === 'string') { + value = COMPLETION_JOB_PREFIX + value + } + + return await this.unsubscribe(value) } async publish (...args) { const { name, data, options } = Attorney.checkPublishArgs(args, this.config) - return this.createJob(name, data, options) + return await this.createJob(name, data, options) } async publishOnce (name, data, options, key) { @@ -237,7 +241,7 @@ class Manager extends EventEmitter { const result = Attorney.checkPublishArgs([name, data, options], this.config) - return this.createJob(result.name, result.data, result.options) + return await this.createJob(result.name, result.data, result.options) } async publishSingleton (name, data, options) { @@ -247,7 +251,7 @@ class Manager extends EventEmitter { const result = Attorney.checkPublishArgs([name, data, options], this.config) - return this.createJob(result.name, result.data, result.options) + return await this.createJob(result.name, result.data, result.options) } async publishAfter (name, data, options, after) { @@ -256,7 +260,7 @@ class Manager extends EventEmitter { const result = Attorney.checkPublishArgs([name, data, options], this.config) - return this.createJob(result.name, result.data, result.options) + return await this.createJob(result.name, result.data, result.options) } async publishThrottled (name, data, options, seconds, key) { @@ -267,7 +271,7 @@ class Manager extends EventEmitter { const result = Attorney.checkPublishArgs([name, data, options], this.config) - return this.createJob(result.name, result.data, result.options) + return await this.createJob(result.name, result.data, result.options) } async publishDebounced (name, data, options, seconds, key) { @@ -278,7 +282,7 @@ class Manager extends EventEmitter { const result = Attorney.checkPublishArgs([name, data, options], this.config) - return this.createJob(result.name, result.data, result.options) + return await this.createJob(result.name, result.data, result.options) } async createJob (name, data, options, singletonOffset = 0) { @@ -332,7 +336,7 @@ class Manager extends EventEmitter { singletonOffset = singletonSeconds - return this.createJob(name, data, options, singletonOffset) + return await this.createJob(name, data, options, singletonOffset) } getDebounceStartAfter (singletonSeconds, clockOffset) { @@ -382,7 +386,7 @@ class Manager extends EventEmitter { } async fetchCompleted (name, batchSize, options = {}) { - return this.fetch(COMPLETION_JOB_PREFIX + name, batchSize, options) + return await this.fetch(COMPLETION_JOB_PREFIX + name, batchSize, options) } mapCompletionIdArg (id, funcName) { diff --git a/test/completeTest.js b/test/completeTest.js index b6621be7..43a353c3 100644 --- a/test/completeTest.js +++ b/test/completeTest.js @@ -134,7 +134,7 @@ describe('complete', function () { let receivedCount = 0 - boss.onComplete(jobName, async job => { + boss.onComplete(jobName, { newJobCheckInterval: 500 }, async job => { receivedCount++ await boss.offComplete(jobName) }) @@ -154,6 +154,30 @@ describe('complete', function () { assert.strictEqual(receivedCount, 1) }) + it('should unsubscribe an onComplete subscription by id', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) + const queue = this.test.bossConfig.schema + + let receivedCount = 0 + + await boss.publish(queue) + const job1 = await boss.fetch(queue) + await boss.complete(job1.id) + + await boss.publish(queue) + const job2 = await boss.fetch(queue) + await boss.complete(job2.id) + + const id = await boss.onComplete(queue, { newJobCheckInterval: 500 }, async () => { + receivedCount++ + await boss.offComplete({ id }) + }) + + await delay(2000) + + assert.strictEqual(receivedCount, 1) + }) + it('should fetch a completed job', async function () { const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, onComplete: true }) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index 4cd214ba..26d19b0b 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -88,6 +88,25 @@ describe('subscribe', function () { assert.strictEqual(receivedCount, 1) }) + it('should unsubscribe a subscription by id', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = this.test.bossConfig.schema + + let receivedCount = 0 + + await boss.publish(queue) + await boss.publish(queue) + + const id = await boss.subscribe(queue, { newJobCheckInterval: 500 }, async () => { + receivedCount++ + await boss.unsubscribe({ id }) + }) + + await delay(2000) + + assert.strictEqual(receivedCount, 1) + }) + it('should handle a batch of jobs via teamSize', async function () { const boss = this.test.boss = await helper.start(this.test.bossConfig) From f6a69b6a8fed899d04985a18bdd3b4d3f7d88cb9 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 4 May 2021 22:27:51 -0500 Subject: [PATCH 14/19] added output to archive op + docs --- CHANGELOG.md | 4 ++-- docs/configuration.md | 7 +++---- docs/usage.md | 5 +++++ src/plans.js | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5b111b4..c49b9434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,9 @@ ## 6.0.0 :tada: -- CHANGE: `stop()` has been enhanced with a **graceful stop** feature that will signal and monitor any polling subscriptions (workers using `subscribe()` or `onComlete()`) before closing the internal connection pool and stopping maintenance operations. The defalt options, `{ graceful = true, timeout = 30000 }`, will wait up to 30s before shutting down. +- CHANGE: `stop()` has been enhanced with a graceful stop feature that will signal and monitor any polling subscriptions (workers using `subscribe()` or `onComlete()`) before closing the internal connection pool and stopping maintenance operations. The defalt options, `{ graceful = true, timeout = 30000 }`, will wait for 30s before shutting down. - NEW: Added a `stopped` event that will be emitted after `stop()` when all workers have completed active jobs, or when the timeout is met, whichever is sooner. -- NEW: Added a `wip` event that will emit as jobs are both fetched and completed. If no work is being done, no events will be emitted. This will emit at most once every 2 seconds for monitoring purposes. +- NEW: Added a `wip` event that will emit as jobs are both fetched and completed per instance. If no work is being done, no events will be emitted. This will emit at most once every 2 seconds for monitoring purposes. - NEW: Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. - NEW: `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. - NEW: Added new function, `publishSingleton()`, similar to publishOnce(), but throttles publish to only allow 1 job in the queue at a time, allowing a job to be queued even if 1 or more jobs are currently active. diff --git a/docs/configuration.md b/docs/configuration.md index 68f60abd..7914e2f8 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -74,9 +74,6 @@ Alternatively, the following options can be set as properties in an object. This option may be beneficial if you'd like to use an existing database service with its own connection pool. - For example, you may be relying on the cluster module on - a web server, and you'd like to limit the growth of total connections as much as possible. - * **schema** - string, defaults to "pgboss" Database schema that contains all required storage objects. Only alphanumeric and underscore allowed, length: <= 50 characters @@ -259,7 +256,7 @@ For example, if you set the `singletonMinutes` to 1, then submit 2 jobs within a Setting `singletonNextSlot` to true will cause the job to be scheduled to run after the current time slot if and when a job is throttled. This option is set to true, for example, when calling the convenience function `publishDebounced()`. ### Completion jobs -* **onComplete**, bool (Default: true) +* **onComplete**, bool (Default: false) When a job completes, a completion job will be created in the queue, copying the same retention policy as the job, for the purpose of `onComplete()` or `fetchCompleted()`. If completion jobs are not used, they will be archived according to the retention policy. If the queue in question has a very high volume, this can be set to `false` to bypass creating the completion job. This can also be set in the constructor as a default for all calls to `publish()`. @@ -288,6 +285,8 @@ When a job completes, a completion job will be created in the queue, copying the | createdon | string, timestamp | | completedon | string, timestamp | | keepuntil | string, timestamp | + | oncomplete | bool | + | output | object | ## Subscribe options diff --git a/docs/usage.md b/docs/usage.md index f55dacd0..e2cd14b3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -50,6 +50,7 @@ - [`fail(id [, data])`](#failid--data) - [`fail([ids])`](#failids) - [`getQueueSize(name [, options])`](#getqueuesizename--options) + - [`getJobById(id)`](#getjobbyidid) - [`deleteQueue(name)`](#deletequeuename) - [`deleteAllQueues()`](#deleteallqueues) - [`clearStorage()`](#clearstorage) @@ -679,6 +680,10 @@ As an example, the following options object include active jobs along with creat } ``` +## `getJobById(id)` + +Retrieves a job with all metadata by id in either the primary or archive storage. + ## `deleteQueue(name)` Deletes all pending jobs in the specified queue from the active job table. All jobs in the archive table are retained. diff --git a/src/plans.js b/src/plans.js index bf4cb9e4..38785b8d 100644 --- a/src/plans.js +++ b/src/plans.js @@ -567,10 +567,10 @@ function archive (schema, interval) { RETURNING * ) INSERT INTO ${schema}.archive ( - id, name, priority, data, state, retryLimit, retryCount, retryDelay, retryBackoff, startAfter, startedOn, singletonKey, singletonOn, expireIn, createdOn, completedOn, keepUntil, on_complete + id, name, priority, data, state, retryLimit, retryCount, retryDelay, retryBackoff, startAfter, startedOn, singletonKey, singletonOn, expireIn, createdOn, completedOn, keepUntil, on_complete, output ) SELECT - id, name, priority, data, state, retryLimit, retryCount, retryDelay, retryBackoff, startAfter, startedOn, singletonKey, singletonOn, expireIn, createdOn, completedOn, keepUntil, on_complete + id, name, priority, data, state, retryLimit, retryCount, retryDelay, retryBackoff, startAfter, startedOn, singletonKey, singletonOn, expireIn, createdOn, completedOn, keepUntil, on_complete, output FROM archived_rows ` } From a92840456bf52577ad8f243f60b2db542eb29e88 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Tue, 4 May 2021 22:32:03 -0500 Subject: [PATCH 15/19] readme update [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c7b2edf..13e7a9fb 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ This will likely cater the most to teams already familiar with the simplicity of * Automatic maintenance operations to manage table growth ## Requirements -* Node 10 or higher +* Node 12 or higher * PostgreSQL 9.5 or higher ## Installation From c7c331b6db513274fca974108a85e87fbe44b232 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Wed, 5 May 2021 18:28:45 -0500 Subject: [PATCH 16/19] fixes --- CHANGELOG.md | 4 +-- docs/usage.md | 1 + package.json | 6 ++-- src/boss.js | 18 ++++++----- src/index.js | 2 ++ src/manager.js | 68 ++++++++++++++++++++++++----------------- src/timekeeper.js | 1 + src/worker.js | 2 ++ test/opsTest.js | 70 ++++++++++++++++++++++++++++++++++++++++++- test/subscribeTest.js | 14 +++++++++ 10 files changed, 146 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c49b9434..8f8ab472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,13 +8,13 @@ - NEW: Added the `output` jsonb column to storage tables to store result or error data along with the original job, which were previously only available via completion jobs. This has the added benefit of storing any errors or results from completion jobs themselves, which were previously discarded. - NEW: `getJobById(id)` can now be used to fetch a job from either primary or archive storage by id. This may be helpful if needed to inspect `output` and you have the job id. - NEW: Added new function, `publishSingleton()`, similar to publishOnce(), but throttles publish to only allow 1 job in the queue at a time, allowing a job to be queued even if 1 or more jobs are currently active. -- CHANGE: `subscribe()` and `onComplete()` now resolve with a unique worker id that will be visible in `wip` along with additional metadata about the subscription. +- CHANGE: `subscribe()` and `onComplete()` now resolve with a unique id that will be visible in `wip` along with additional metadata about the subscription. - CHANGE: `subscribe()` and `onComplete()` now abort promise execution client-side based on the job's expiration. - CHANGE: `unsubscribe()` and `offComplete()` now accept an object as an argument to allow removing a specific subscription by id. - MAJOR: The `onComplete` publish option is now defaulted to `false`, which breaks backward compatability for automatic creation of completion jobs. To restore the previous behavior of completion jobs being created by default, you should set `onComplete` to `true` in your constructor options. - MAJOR: The default retention policy has been reduced from 30 to 14 days. This can still be customized as an option in the constructor. - MAJOR: Node 10 is EOL. Node 12 is now the minimum supported version. -- MAJOR: Added a new index to the primary job table to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` promise resolution. If this is a concern, you can fetch the new schema version via `getMigrationPlans()` and create the indexes out of band. The migration includes an `IF NOT EXISTS` to bypass creation. +- MAJOR: Added a new index to the primary job table, `job_fetch`, to improve fetch time performace as the job table size increases. Depending on how many jobs you have in your job table, creating this index may delay `start()` promise resolution. If this is a concern, you can get the DDL via `getMigrationPlans()` and create the index out of band. The DLL includes an `IF NOT EXISTS` which will skip this step in the migration if already created. In the following example, once you have installed this package version, using the node repl, you can get the DDL for the index from `getMigrationPlans()`. diff --git a/docs/usage.md b/docs/usage.md index e2cd14b3..520b1b07 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -207,6 +207,7 @@ Emitted at most once every 2 seconds when polling subscriptions are active and j lastFetchedOn: 1620149137015, lastJobStartedOn: 1620149137015, lastJobEndedOn: null, + lastJobDuration: 343 lastError: null, lastErrorOn: null } diff --git a/package.json b/package.json index 07dedc3b..64fa648d 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "standard": "^16.0.3" }, "scripts": { - "test": "standard && mocha --exit --no-warnings --parallel --require ./test/hooks", + "test": "standard && mocha", "cover": "nyc --reporter=text npm test", "forcover": "npm run cover && nyc report --reporter=text-lcov | coveralls", "export-schema": "node ./scripts/construct.js", @@ -32,7 +32,9 @@ "mocha": { "timeout": 10000, "slow": 10000, - "bail": true + "bail": true, + "parallel": true, + "require": "./test/hooks" }, "nyc": { "include": [ diff --git a/src/boss.js b/src/boss.js index 57fadad0..bedc389d 100644 --- a/src/boss.js +++ b/src/boss.js @@ -160,6 +160,10 @@ class Boss extends EventEmitter { } async stop () { + if (this.config.__test__throw_stop) { + throw new Error('__test__throw_stop') + } + if (!this.stopped) { if (this.metaMonitorInterval) { clearInterval(this.metaMonitorInterval) @@ -217,17 +221,15 @@ class Boss extends EventEmitter { } async getMaintenanceTime () { - if (this.stopped) { - return - } - - const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand) + if (!this.stopped) { + const { rows } = await this.db.executeSql(this.getMaintenanceTimeCommand) - let { maintained_on: maintainedOn, seconds_ago: secondsAgo } = rows[0] + let { maintained_on: maintainedOn, seconds_ago: secondsAgo } = rows[0] - secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : this.maintenanceIntervalSeconds * 10 + secondsAgo = secondsAgo !== null ? parseFloat(secondsAgo) : this.maintenanceIntervalSeconds * 10 - return { maintainedOn, secondsAgo } + return { maintainedOn, secondsAgo } + } } getQueueNames () { diff --git a/src/index.js b/src/index.js index 12ba33c1..83552c9c 100644 --- a/src/index.js +++ b/src/index.js @@ -100,6 +100,8 @@ class PgBoss extends EventEmitter { await this.contractor.start() + this.manager.start() + if (!this.config.noSupervisor) { await this.boss.supervise() } diff --git a/src/manager.js b/src/manager.js index f229bef4..2139f8c6 100644 --- a/src/manager.js +++ b/src/manager.js @@ -9,9 +9,9 @@ const Attorney = require('./attorney') const Worker = require('./worker') const { QUEUES: BOSS_QUEUES } = require('./boss') -const HIDDEN_QUEUES = Object.values(BOSS_QUEUES) +const { QUEUES: TIMEKEEPER_QUEUES } = require('./timekeeper') -// todo: add cron and send it queues to ignore list +const INTERNAL_QUEUES = Object.values(BOSS_QUEUES).concat(Object.values(TIMEKEEPER_QUEUES)).reduce((acc, i) => ({ ...acc, [i]: i }), {}) const plans = require('./plans') const { COMPLETION_JOB_PREFIX, SINGLETON_QUEUE_KEY } = plans @@ -39,6 +39,8 @@ class Manager extends EventEmitter { this.completeJobsCommand = plans.completeJobs(config.schema) this.cancelJobsCommand = plans.cancelJobs(config.schema) this.failJobsCommand = plans.failJobs(config.schema) + this.getJobByIdCommand = plans.getJobById(config.schema) + this.getArchivedJobByIdCommand = plans.getArchivedJobById(config.schema) // exported api to index this.functions = [ @@ -67,13 +69,17 @@ class Manager extends EventEmitter { this.emitWipThrottled = debounce(() => this.emit(events.wip, this.getWipData()), WIP_EVENT_INTERVAL, WIP_DEBOUNCE_OPTIONS) } + start () { + this.stopping = false + } + async stop () { + this.stopping = true + for (const sub of this.subscriptions.values()) { - if (HIDDEN_QUEUES.includes(sub.name)) { - continue + if (!INTERNAL_QUEUES[sub.name]) { + await this.unsubscribe(sub.name) } - - await this.unsubscribe(sub.name) } } @@ -99,6 +105,12 @@ class Manager extends EventEmitter { return Array.from(this.subscriptions.values()) } + emitWip (name) { + if (!INTERNAL_QUEUES[name]) { + this.emitWipThrottled() + } + } + getWipData () { const data = this.getWorkers() .map(({ @@ -126,12 +138,16 @@ class Manager extends EventEmitter { lastError, lastErrorOn })) - .filter(i => i.count > 0 && !HIDDEN_QUEUES.includes(i.name)) + .filter(i => i.count > 0 && !INTERNAL_QUEUES[i.name]) return data } async watch (name, options, callback) { + if (this.stopping) { + throw new Error('Subscriptions are disabled. pg-boss is stopping.') + } + const { newJobCheckInterval: interval = this.config.newJobCheckInterval, batchSize, @@ -145,35 +161,35 @@ class Manager extends EventEmitter { const fetch = () => this.fetch(name, batchSize || teamSize, { includeMetadata }) const onFetch = async (jobs) => { + if (this.config.__test__throw_subscription) { + throw new Error('__test__throw_subscription') + } + const expirationRace = (promise, timeout) => Promise.race([ promise, delay.reject(timeout, { value: new Error('job handler timeout exceeded in subscription') }) ]) - if (!HIDDEN_QUEUES.includes(name)) { - this.emitWipThrottled() - } + this.emitWip(name) let result - // Failing will fail all fetched jobs if (batchSize) { - const maxMs = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein))) + const maxTimeout = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein))) - result = await expirationRace(Promise.all([callback(jobs)]), maxMs) + // Failing will fail all fetched jobs + result = await expirationRace(Promise.all([callback(jobs)]), maxTimeout) .catch(err => this.fail(jobs.map(job => job.id), err)) + } else { + result = await pMap(jobs, job => + expirationRace(callback(job), plans.intervalToMs(job.expirein)) + .then(result => this.complete(job.id, result)) + .catch(err => this.fail(job.id, err)) + , { concurrency: teamConcurrency } + ).catch(() => {}) // allow promises & non-promises to live together in harmony } - result = await pMap(jobs, job => - expirationRace(callback(job), plans.intervalToMs(job.expirein)) - .then(result => this.complete(job.id, result)) - .catch(err => this.fail(job.id, err)) - , { concurrency: teamConcurrency } - ).catch(() => {}) // allow promises & non-promises to live together in harmony - - if (!HIDDEN_QUEUES.includes(name)) { - this.emitWipThrottled() - } + this.emitWip(name) return result } @@ -466,15 +482,13 @@ class Manager extends EventEmitter { } async getJobById (id) { - const fetchSql = plans.getJobById(this.config.schema) - const result1 = await this.db.executeSql(fetchSql, [id]) + const result1 = await this.db.executeSql(this.getJobByIdCommand, [id]) if (result1 && result1.rows && result1.rows.length === 1) { return result1.rows[0] } - const fetchArchiveSql = plans.getArchivedJobById(this.config.schema) - const result2 = await this.db.executeSql(fetchArchiveSql, [id]) + const result2 = await this.db.executeSql(this.getArchivedJobByIdCommand, [id]) if (result2 && result2.rows && result2.rows.length === 1) { return result2.rows[0] diff --git a/src/timekeeper.js b/src/timekeeper.js index 470f69b5..834bf6b5 100644 --- a/src/timekeeper.js +++ b/src/timekeeper.js @@ -210,3 +210,4 @@ class Timekeeper extends EventEmitter { } module.exports = Timekeeper +module.exports.QUEUES = queues diff --git a/src/worker.js b/src/worker.js index ec9e03ea..382cc1f7 100644 --- a/src/worker.js +++ b/src/worker.js @@ -61,6 +61,8 @@ class Worker { const duration = Date.now() - started + this.lastJobDuration = duration + if (!this.stopping && duration < this.interval) { await delay(this.interval - duration) } diff --git a/test/opsTest.js b/test/opsTest.js index e8997592..6c9c1e1b 100644 --- a/test/opsTest.js +++ b/test/opsTest.js @@ -1,8 +1,12 @@ +const assert = require('assert') const helper = require('./testHelper') +const { v4: uuid } = require('uuid') +const delay = require('delay') describe('ops', function () { const defaults = { - noSupervisor: true + noSupervisor: true, + noScheduling: true } it('should expire manually', async function () { @@ -19,4 +23,68 @@ describe('ops', function () { const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) await boss.purge() }) + + it('stop should re-emit stoppped if already stopped', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + + const stopPromise1 = new Promise(resolve => boss.once('stopped', resolve)) + + await boss.stop({ timeout: 1 }) + + await stopPromise1 + + const stopPromise2 = new Promise(resolve => boss.once('stopped', resolve)) + + await boss.stop({ timeout: 1 }) + + await stopPromise2 + }) + + it('should emit error in subscription', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, __test__throw_subscription: true }) + const queue = this.test.bossConfig.schema + + await boss.publish(queue) + await boss.subscribe(queue, () => {}) + + await new Promise(resolve => boss.once('error', resolve)) + }) + + it('should return null from getJobById if not found', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + + const jobId = await boss.getJobById(uuid()) + + assert.strictEqual(jobId, null) + }) + + it('should force stop', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults }) + await boss.stop({ graceful: false }) + }) + + it('should emit error during graceful stop if subscriptions busy', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, __test__throw_stop: true }) + const queue = this.test.bossConfig.schema + + await boss.publish(queue) + await boss.subscribe(queue, () => delay(2000)) + + await delay(500) + + await boss.stop({ timeout: 5000 }) + + await new Promise(resolve => boss.on('error', resolve)) + }) + + it('should throw error during graceful stop if no subscriptions are busy', async function () { + const boss = this.test.boss = await helper.start({ ...this.test.bossConfig, ...defaults, __test__throw_stop: true }) + + try { + await boss.stop({ timeout: 1 }) + assert(false) + } catch (err) { + assert(true) + } + }) }) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index 26d19b0b..f1af3df1 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -345,4 +345,18 @@ describe('subscribe', function () { assert.strictEqual(wip2.length, 0) }) + + it('should reject subscribe() after stopping', async function () { + const boss = this.test.boss = await helper.start(this.test.bossConfig) + const queue = this.test.bossConfig.schema + + boss.stop({ timeout: 1 }) + + try { + await boss.subscribe(queue) + assert(false) + } catch (err) { + assert(err.message.includes('stopping')) + } + }) }) From 6bbadcda6a04b58f6d69c270f56dbf068e506c18 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Wed, 5 May 2021 23:14:39 -0500 Subject: [PATCH 17/19] added timeout to error message --- src/manager.js | 2 +- test/subscribeTest.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/manager.js b/src/manager.js index 2139f8c6..576e0080 100644 --- a/src/manager.js +++ b/src/manager.js @@ -167,7 +167,7 @@ class Manager extends EventEmitter { const expirationRace = (promise, timeout) => Promise.race([ promise, - delay.reject(timeout, { value: new Error('job handler timeout exceeded in subscription') }) + delay.reject(timeout, { value: new Error(`handler execution exceeded ${timeout}ms`) }) ]) this.emitWip(name) diff --git a/test/subscribeTest.js b/test/subscribeTest.js index f1af3df1..2dfc4039 100644 --- a/test/subscribeTest.js +++ b/test/subscribeTest.js @@ -293,7 +293,7 @@ describe('subscribe', function () { const job = await boss.getJobById(jobId) assert.strictEqual(job.state, 'failed') - assert(job.output.message.includes('timeout')) + assert(job.output.message.includes('handler execution exceeded')) }) it('should fail a batch of jobs at expiration without maintenance', async function () { @@ -320,10 +320,10 @@ describe('subscribe', function () { const job2 = await boss.getJobById(jobId2) assert.strictEqual(job1.state, 'failed') - assert(job1.output.message, 'job handler timeout exceeded in subscription') + assert(job1.output.message.includes('handler execution exceeded')) assert.strictEqual(job2.state, 'failed') - assert(job2.output.message, 'job handler timeout exceeded in subscription') + assert(job2.output.message.includes('handler execution exceeded')) }) it('should emit wip event every 2s during subscriptions', async function () { From c8c3fc466f8d027aa9dbbed18bf9d112afcaab5d Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Wed, 5 May 2021 23:41:13 -0500 Subject: [PATCH 18/19] fix max timeout for batchSize --- src/manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager.js b/src/manager.js index 576e0080..88a26d6e 100644 --- a/src/manager.js +++ b/src/manager.js @@ -175,7 +175,7 @@ class Manager extends EventEmitter { let result if (batchSize) { - const maxTimeout = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein))) + const maxTimeout = jobs.reduce((acc, i) => Math.max(acc, plans.intervalToMs(i.expirein)), 0) // Failing will fail all fetched jobs result = await expirationRace(Promise.all([callback(jobs)]), maxTimeout) From 7f30d1852d11a60f7d60d6561c923198581ce7e3 Mon Sep 17 00:00:00 2001 From: Tim Jones Date: Sat, 8 May 2021 16:37:31 -0500 Subject: [PATCH 19/19] added early abort to worker loop delay during stop --- src/worker.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/worker.js b/src/worker.js index 382cc1f7..9b2141be 100644 --- a/src/worker.js +++ b/src/worker.js @@ -26,6 +26,7 @@ class Worker { this.state = WORKER_STATES.created this.stopping = false this.stopped = false + this.loopDelayPromise = null } async start () { @@ -64,7 +65,9 @@ class Worker { this.lastJobDuration = duration if (!this.stopping && duration < this.interval) { - await delay(this.interval - duration) + this.loopDelayPromise = delay(this.interval - duration) + await this.loopDelayPromise + this.loopDelayPromise = null } } @@ -76,6 +79,10 @@ class Worker { stop () { this.stopping = true this.state = WORKER_STATES.stopping + + if (this.loopDelayPromise) { + this.loopDelayPromise.clear() + } } }