diff --git a/package-lock.json b/package-lock.json index 469b091..62ec608 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@types/node": "^12.20.55", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", - "typescript": "^4.8.4" + "typescript": "^5.4.2" }, "engines": { "node": ">=10" @@ -1975,16 +1975,16 @@ } }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/well-known-symbols": { @@ -2216,5 +2216,1548 @@ "url": "https://github.com/sponsors/sindresorhus" } } + }, + "dependencies": { + "@ava/typescript": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@ava/typescript/-/typescript-3.0.1.tgz", + "integrity": "sha512-/JXIUuKsvkaneaiA9ckk3ksFTqvu0mDNlChASrTe2BnDsvMbhQdPWyqQjJ9WRJWVhhs5TWn1/0Pp1G6Rv8Syrw==", + "dev": true, + "requires": { + "escape-string-regexp": "^5.0.0", + "execa": "^5.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true + }, + "@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "dependencies": { + "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==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.1.tgz", + "integrity": "sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==", + "dev": true + }, + "anymatch": { + "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", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrgv": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", + "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", + "dev": true + }, + "arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true + }, + "ava": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/ava/-/ava-4.3.3.tgz", + "integrity": "sha512-9Egq/d9R74ExrWohHeqUlexjDbgZJX5jA1Wq4KCTqc3wIfpGEK79zVy4rBtofJ9YKIxs4PzhJ8BgbW5PlAYe6w==", + "dev": true, + "requires": { + "acorn": "^8.7.1", + "acorn-walk": "^8.2.0", + "ansi-styles": "^6.1.0", + "arrgv": "^1.0.2", + "arrify": "^3.0.0", + "callsites": "^4.0.0", + "cbor": "^8.1.0", + "chalk": "^5.0.1", + "chokidar": "^3.5.3", + "chunkd": "^2.0.1", + "ci-info": "^3.3.1", + "ci-parallel-vars": "^1.0.1", + "clean-yaml-object": "^0.1.0", + "cli-truncate": "^3.1.0", + "code-excerpt": "^4.0.0", + "common-path-prefix": "^3.0.0", + "concordance": "^5.0.4", + "currently-unhandled": "^0.4.1", + "debug": "^4.3.4", + "del": "^6.1.1", + "emittery": "^0.11.0", + "figures": "^4.0.1", + "globby": "^13.1.1", + "ignore-by-default": "^2.1.0", + "indent-string": "^5.0.0", + "is-error": "^2.2.2", + "is-plain-object": "^5.0.0", + "is-promise": "^4.0.0", + "matcher": "^5.0.0", + "mem": "^9.0.2", + "ms": "^2.1.3", + "p-event": "^5.0.1", + "p-map": "^5.4.0", + "picomatch": "^2.3.1", + "pkg-conf": "^4.0.0", + "plur": "^5.1.0", + "pretty-ms": "^7.0.1", + "resolve-cwd": "^3.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.5", + "strip-ansi": "^7.0.1", + "supertap": "^3.0.1", + "temp-dir": "^2.0.0", + "write-file-atomic": "^4.0.1", + "yargs": "^17.5.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "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 + }, + "blueimp-md5": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", + "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", + "dev": true + }, + "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, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "callsites": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.0.0.tgz", + "integrity": "sha512-y3jRROutgpKdz5vzEhWM34TidDU8vkJppF8dszITeb1PQmSqV3DTxyV8G/lyO/DNvtE1YTedehmw9MPZsCBHxQ==", + "dev": true + }, + "cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "requires": { + "nofilter": "^3.1.0" + } + }, + "chalk": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.1.0.tgz", + "integrity": "sha512-56zD4khRTBoIyzUYAFgDDaPhUMN/fC/rySe6aZGqbj/VWiU2eI3l6ZLOtYGFZAV5v02mwPjtpzlrOveJiz5eZQ==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chunkd": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", + "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", + "dev": true + }, + "ci-info": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.5.0.tgz", + "integrity": "sha512-yH4RezKOGlOhxkmhbeNuC4eYZKAUsEaGtBuBzDDP1eFUKiccDWzBABxBfOx31IDwDIXMTxWuwAxUGModvkbuVw==", + "dev": true + }, + "ci-parallel-vars": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", + "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clean-yaml-object": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", + "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", + "dev": true + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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 + }, + "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 + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "code-excerpt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", + "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", + "dev": true, + "requires": { + "convert-to-spaces": "^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 + }, + "common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "concordance": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", + "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", + "dev": true, + "requires": { + "date-time": "^3.1.0", + "esutils": "^2.0.3", + "fast-diff": "^1.2.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.15", + "md5-hex": "^3.0.1", + "semver": "^7.3.2", + "well-known-symbols": "^2.0.0" + } + }, + "convert-to-spaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", + "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", + "dev": true + }, + "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, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "date-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", + "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", + "dev": true, + "requires": { + "time-zone": "^1.0.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "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 + } + } + }, + "del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "dependencies": { + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "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==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "emittery": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.11.0.tgz", + "integrity": "sha512-S/7tzL6v5i+4iJd627Nhv9cLFIo5weAIlGccqJFpnBoDB8U1TF2k5tez4J/QNuxyyhWuFqHg1L84Kd3m7iXg6g==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true + }, + "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 + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "figures": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-4.0.1.tgz", + "integrity": "sha512-rElJwkA/xS04Vfg+CaZodpso7VqBknOYbzi6I76hI4X80RUjkSxO2oAyPmGbuXUppywjqndOrQDl817hDnI++w==", + "dev": true, + "requires": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + } + }, + "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, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "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 + }, + "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 + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "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" + } + }, + "globby": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", + "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "dev": true, + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "dependencies": { + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "ignore-by-default": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", + "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "irregular-plurals": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.3.0.tgz", + "integrity": "sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g==", + "dev": true + }, + "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, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-error": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", + "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "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 + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true + }, + "js-yaml": { + "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", + "esprima": "^4.0.0" + } + }, + "load-json-file": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", + "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", + "dev": true + }, + "locate-path": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.1.1.tgz", + "integrity": "sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "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, + "requires": { + "yallist": "^4.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "matcher": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", + "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", + "dev": true, + "requires": { + "escape-string-regexp": "^5.0.0" + } + }, + "md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "requires": { + "blueimp-md5": "^2.10.0" + } + }, + "mem": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", + "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^4.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "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 + }, + "nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true + }, + "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 + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true + }, + "p-event": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", + "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", + "dev": true, + "requires": { + "p-timeout": "^5.0.2" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "requires": { + "aggregate-error": "^4.0.0" + }, + "dependencies": { + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + } + } + }, + "p-timeout": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", + "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "dev": true + }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "dev": true + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "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 + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pkg-conf": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", + "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", + "dev": true, + "requires": { + "find-up": "^6.0.0", + "load-json-file": "^7.0.0" + } + }, + "plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", + "dev": true, + "requires": { + "irregular-plurals": "^3.3.0" + } + }, + "pretty-ms": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", + "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", + "dev": true, + "requires": { + "parse-ms": "^2.1.0" + } + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "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 + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "requires": { + "type-fest": "^0.13.1" + } + }, + "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, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "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 + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "supertap": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", + "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", + "dev": true, + "requires": { + "indent-string": "^5.0.0", + "js-yaml": "^3.14.1", + "serialize-error": "^7.0.1", + "strip-ansi": "^7.0.1" + } + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true + }, + "time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", + "dev": true + }, + "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, + "requires": { + "is-number": "^7.0.0" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true + }, + "typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "dev": true + }, + "well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true + }, + "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" + } + }, + "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, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "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" + } + }, + "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 + }, + "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 + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs": { + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.0.tgz", + "integrity": "sha512-8H/wTDqlSwoSnScvV2N/JHfLWOKuh5MVla9hqLjK3nsfyy6Y4kDSYSvkU5YCUEPOSnRXfIyx3Sq+B/IWudTo4g==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "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 + }, + "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 + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } } } diff --git a/package.json b/package.json index 737ac2a..32905e0 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,6 @@ "@types/node": "^12.20.55", "@types/sinonjs__fake-timers": "^8.1.5", "ava": "^4.3.3", - "typescript": "^4.8.4" + "typescript": "^5.4.2" } } diff --git a/spec/ClearSubstitute.spec.ts b/spec/ClearSubstitute.spec.ts index 4c85557..f16339d 100644 --- a/spec/ClearSubstitute.spec.ts +++ b/spec/ClearSubstitute.spec.ts @@ -1,7 +1,7 @@ import test from 'ava' import { Substitute, SubstituteOf, clearReceivedCalls, received, returns } from '../src' -import { SubstituteNode } from '../src/SubstituteNode' +import { SubstituteNode, instance } from '../src/SubstituteNode' interface Calculator { add(a: number, b: number): number @@ -11,18 +11,18 @@ interface Calculator { } type InstanceReturningSubstitute = SubstituteOf & { - [SubstituteNode.instance]: SubstituteNode + [instance]: SubstituteNode } test('clears received calls on a substitute', t => { const calculator = Substitute.for() as InstanceReturningSubstitute calculator.add(1, 1) - calculator.add(1, 1)[returns](2) - calculator[clearReceivedCalls](); + calculator.add(1, 1).returns(2) + calculator.clearReceivedCalls(); - t.is(calculator[SubstituteNode.instance].recorder.records.size, 2) - t.is(calculator[SubstituteNode.instance].recorder.indexedRecords.size, 2) + t.is(calculator[instance].recorder.records.size, 2) + t.is(calculator[instance].recorder.indexedRecords.size, 2) - t.throws(() => calculator[received]().add(1, 1)) + t.throws(() => calculator.received().add(1, 1)) t.is(2, calculator.add(1, 1)) }) \ No newline at end of file diff --git a/spec/Recorder.spec.ts b/spec/Recorder.spec.ts index 14a96f0..a743e26 100644 --- a/spec/Recorder.spec.ts +++ b/spec/Recorder.spec.ts @@ -8,7 +8,7 @@ import { returns } from '../src' const nodeFactory = (key: string) => { const node = Substitute.for() - node.key[returns](key) + node.key.returns(key) return node } diff --git a/spec/regression/didNotReceive.spec.ts b/spec/regression/didNotReceive.spec.ts index 3eaad21..55f4dba 100644 --- a/spec/regression/didNotReceive.spec.ts +++ b/spec/regression/didNotReceive.spec.ts @@ -12,41 +12,41 @@ interface Calculator { test('not calling a method correctly asserts the call count', t => { const calculator = Substitute.for() - calculator[didNotReceive]().add(1, 1) - t.throws(() => calculator[received]().add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().add(Arg.all()), { instanceOf: SubstituteException }) + calculator.didNotReceive().add(1, 1) + t.throws(() => calculator.received().add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }) }) test('not getting a property correctly asserts the call count', t => { const calculator = Substitute.for() - calculator[didNotReceive]().isEnabled - t.throws(() => calculator[received](1).isEnabled, { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().isEnabled, { instanceOf: SubstituteException }) + calculator.didNotReceive().isEnabled + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }) }) test('not setting a property correctly asserts the call count', t => { const calculator = Substitute.for() - calculator[didNotReceive]().isEnabled = true - t.throws(() => calculator[received](1).isEnabled = true, { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().isEnabled = true, { instanceOf: SubstituteException }) + calculator.didNotReceive().isEnabled = true + t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled = true, { instanceOf: SubstituteException }) }) test('not calling a method with mock correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.add(1, 1)[returns](2) + calculator.add(1, 1).returns(2) - calculator[didNotReceive]().add(1, 1) - t.throws(() => calculator[received](1).add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().add(Arg.all()), { instanceOf: SubstituteException }) + calculator.didNotReceive().add(1, 1) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(Arg.all()), { instanceOf: SubstituteException }) }) test('not getting a property with mock correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.isEnabled[returns](true) + calculator.isEnabled.returns(true) - calculator[didNotReceive]().isEnabled - t.throws(() => calculator[received](1).isEnabled, { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().isEnabled, { instanceOf: SubstituteException }) + calculator.didNotReceive().isEnabled + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled, { instanceOf: SubstituteException }) }) \ No newline at end of file diff --git a/spec/regression/index.test.ts b/spec/regression/index.test.ts index 241069d..33c97de 100644 --- a/spec/regression/index.test.ts +++ b/spec/regression/index.test.ts @@ -20,7 +20,7 @@ export class Example { set v(x: string | null | undefined) { } - received(stuff: number | string) { + received(_stuff: string) { } @@ -28,7 +28,7 @@ export class Example { return Promise.resolve(new Dummy()) } - foo(): string | undefined | null { + foo(_arg?: string): string | undefined | null { return 'stuff' } @@ -48,12 +48,12 @@ function initialize() { const textModifierRegex = /\x1b\[\d+m/g test('class with method called \'received\' can be used for call count verification when using symbols', t => { - initialize() + const substitute = Substitute.for() - substitute.received(2) + substitute.received("foo") - t.throws(() => substitute[received](2).received(2)) - t.notThrows(() => substitute[received](1).received(2)) + t.notThrows(() => substitute[received](1).received("foo")) + t.throws(() => substitute[received](2).received("foo")) }) test('class string field set received', t => { @@ -85,7 +85,7 @@ test('class string field set received', t => { test('resolving promises works', async t => { initialize() - substitute.returnPromise()[resolves](1338) + substitute.returnPromise().resolves(1338) t.is(1338, await substitute.returnPromise() as number) }) @@ -93,7 +93,7 @@ test('resolving promises works', async t => { test('class void returns', t => { initialize() - substitute.foo()[returns](void 0, null) + substitute.foo().returns(void 0, null) t.is(substitute.foo(), void 0) t.is(substitute.foo(), null) @@ -126,7 +126,7 @@ test('class method received', t => { test('received call matches after partial mocks using property instance mimicks', t => { initialize() - substitute.d[mimicks](() => instance.d) + substitute.d.mimicks(() => instance.d) substitute.c('lala', 'bar') substitute[received](1).c('lala', 'bar') @@ -144,7 +144,7 @@ test('received call matches after partial mocks using property instance mimicks' test('partial mocks using property instance mimicks', t => { initialize() - substitute.d[mimicks](() => instance.d) + substitute.d.mimicks(() => instance.d) t.deepEqual(substitute.d, 1337) }) diff --git a/spec/regression/issues/11.test.ts b/spec/regression/issues/11.test.ts index 127526c..64e7b08 100644 --- a/spec/regression/issues/11.test.ts +++ b/spec/regression/issues/11.test.ts @@ -14,12 +14,12 @@ class RealCalculator { test('issue 11: arg.is is only called once', async t => { let mockedCalculator = Substitute.for() - mockedCalculator.add(Arg.any())[returns](4) + mockedCalculator.add(Arg.any()).returns(4) let count = 0 mockedCalculator.add({ op1: 1, op2: 2 }) - mockedCalculator[received](1).add(Arg.is(a => { + mockedCalculator.received(1).add(Arg.is(a => { count++ return a.op1 === 1 && a.op2 === 2 })) diff --git a/spec/regression/issues/178.test.ts b/spec/regression/issues/178.test.ts index 72e8341..018b208 100644 --- a/spec/regression/issues/178.test.ts +++ b/spec/regression/issues/178.test.ts @@ -24,17 +24,17 @@ const throwsUncaughtException = (cb: () => any, t: ExecutionContext, expectation test('can substitute callable interfaces', async t => { const lib = Substitute.for() - lib.subSection()[returns]('subSection as method') - lib.subSection[returns]({ subMethod: () => 'subSection as property' } as Subsection) + lib.subSection().returns('subSection as method') + lib.subSection.returns({ subMethod: () => 'subSection as property' } as Subsection) t.is('subSection as method', lib.subSection()) t.true(types.isProxy(lib.subSection), 'Expected proxy: given the context, it\'s not possible to determine the property type') t.is('subSection as property', lib.subSection.subMethod()) - lib[received]().subSection() - lib[received](1).subSection() - lib[received](2).subSection - t.throws(() => lib[didNotReceive]().subSection(), { instanceOf: SubstituteException }) - t.throws(() => lib[received](2).subSection(), { instanceOf: SubstituteException }) - throwsUncaughtException(() => lib[received](3).subSection, t, { instanceOf: SubstituteException }) + lib.received().subSection() + lib.received(1).subSection() + lib.received(2).subSection + t.throws(() => lib.didNotReceive().subSection(), { instanceOf: SubstituteException }) + t.throws(() => lib.received(2).subSection(), { instanceOf: SubstituteException }) + throwsUncaughtException(() => lib.received(3).subSection, t, { instanceOf: SubstituteException }) }) diff --git a/spec/regression/issues/23.test.ts b/spec/regression/issues/23.test.ts index c4fde96..1126b7e 100644 --- a/spec/regression/issues/23.test.ts +++ b/spec/regression/issues/23.test.ts @@ -14,12 +14,12 @@ test('issue 23: mimick received should not call method', t => { let calls = 0 - mockedCalculator.add(Arg.all())[mimicks]((a, b) => { + mockedCalculator.add(Arg.all()).mimicks((a, b) => { t.deepEqual(++calls, 1, 'mimick called twice') return a + b }) mockedCalculator.add(1, 1) // ok - mockedCalculator[received](1).add(1, 1) // not ok, calls mimick func + mockedCalculator.received(1).add(1, 1) // not ok, calls mimick func }) diff --git a/spec/regression/issues/36.test.ts b/spec/regression/issues/36.test.ts index d9c97ee..9d9be54 100644 --- a/spec/regression/issues/36.test.ts +++ b/spec/regression/issues/36.test.ts @@ -49,7 +49,7 @@ class Service { test('issue 36 - promises returning object with properties', async t => { const emptyFetch = Substitute.for() - emptyFetch.getUpdates(Key.create())[returns](Promise.resolve(IData.create())) + emptyFetch.getUpdates(Key.create()).returns(Promise.resolve(IData.create())) const result = await emptyFetch.getUpdates(Key.create()) t.true(result.serverCheck instanceof Date, 'given date is instanceof Date') t.deepEqual(result.data, [1], 'arrays are deep equal') @@ -58,12 +58,12 @@ test('issue 36 - promises returning object with properties', async t => { test('using objects or classes as arguments should be able to match mock', async t => { const db = Substitute.for() const data = IData.create() - db.getUpdates(Key.create())[returns](Promise.resolve(data)) + db.getUpdates(Key.create()).returns(Promise.resolve(data)) const service = new Service(db) await service.handle(Key.create()) - db[received](1).storeUpdates(Arg.is((arg: IData) => + db.received(1).storeUpdates(Arg.is((arg: IData) => arg.serverCheck instanceof Date && arg instanceof IData && arg.data[0] === 100 diff --git a/spec/regression/issues/45.test.ts b/spec/regression/issues/45.test.ts index c9178b8..9c87540 100644 --- a/spec/regression/issues/45.test.ts +++ b/spec/regression/issues/45.test.ts @@ -30,7 +30,7 @@ test('issue 45 Checking received calls off at times', async t => { subject.callToMethodTwo() t.notThrows(() => { - mock[received](1).methodOne() - mock[received](1).methodTwo(Arg.is(x => x === 'string')) + mock.received(1).methodOne() + mock.received(1).methodTwo(Arg.is(x => x === 'string')) }) }) diff --git a/spec/regression/issues/59.test.ts b/spec/regression/issues/59.test.ts index 72dffc5..fbe6603 100644 --- a/spec/regression/issues/59.test.ts +++ b/spec/regression/issues/59.test.ts @@ -9,10 +9,10 @@ interface IEcho { test('issue 59 - Mock function with optional parameters', (t) => { const echoer = Substitute.for() - echoer.maybeEcho('foo')[returns]('bar') - echoer.maybeEcho()[returns]('baz') + echoer.maybeEcho('foo').returns('bar') + echoer.maybeEcho().returns('baz') t.is('bar', echoer.maybeEcho('foo')) - echoer[received]().maybeEcho('foo') + echoer.received().maybeEcho('foo') t.is('baz', echoer.maybeEcho()) }) diff --git a/spec/regression/mimicks.spec.ts b/spec/regression/mimicks.spec.ts index 4805344..d741131 100644 --- a/spec/regression/mimicks.spec.ts +++ b/spec/regression/mimicks.spec.ts @@ -16,7 +16,7 @@ test('mimicks a method with specific arguments', t => { const calculator = Substitute.for() const addMimick = (a: number, b: number) => a + b - calculator.add(1, 1)[mimicks](addMimick) + calculator.add(1, 1).mimicks(addMimick) t.is(2, calculator.add(1, 1)) }) @@ -24,8 +24,8 @@ test('mimicks a method with specific and conditional arguments', t => { const calculator = Substitute.for() const addMimick = (a: number, b: number) => a + b - calculator.add(Arg.any('number'), Arg.is((input: number) => input >= 0 && input <= 10))[mimicks](addMimick) - calculator.add(42, -42)[mimicks]((a: number, b: number) => 0) + calculator.add(Arg.any('number'), Arg.is((input: number) => input >= 0 && input <= 10)).mimicks(addMimick) + calculator.add(42, -42).mimicks((a: number, b: number) => 0) t.is(1240, calculator.add(1234, 6)) t.is(0, calculator.add(42, -42)) @@ -36,7 +36,7 @@ test('mimicks a method with Arg.all', t => { const addMimick = (a: number, b: number) => a + b - calculator.add(Arg.all())[mimicks](addMimick) + calculator.add(Arg.all()).mimicks(addMimick) t.is(100, calculator.add(42, 58)) }) @@ -45,9 +45,9 @@ test('mimicks a method with optional arguments', t => { const multiplyOneArgMimicks = (a: number) => a * a const multiplyMimicks = (a: number, b?: number) => a * (b ?? 0) - calculator.multiply(0, Arg.is((b: number) => b > 10 && b < 20))[mimicks](multiplyMimicks) - calculator.multiply(Arg.any('number'), Arg.is((b: number) => b === 2))[mimicks](multiplyMimicks) - calculator.multiply(2)[mimicks](multiplyOneArgMimicks) + calculator.multiply(0, Arg.is((b: number) => b > 10 && b < 20)).mimicks(multiplyMimicks) + calculator.multiply(Arg.any('number'), Arg.is((b: number) => b === 2)).mimicks(multiplyMimicks) + calculator.multiply(2).mimicks(multiplyOneArgMimicks) t.is(0, calculator.multiply(0, 13)) t.is(84, calculator.multiply(42, 2)) @@ -57,8 +57,8 @@ test('mimicks a method with optional arguments', t => { test('mimicks a method where it\'s only argument is optional', t => { const calculator = Substitute.for() - calculator.viewResult()[mimicks](() => 0) - calculator.viewResult(3)[mimicks](() => 42) + calculator.viewResult().mimicks(() => 0) + calculator.viewResult(3).mimicks(() => 42) t.is(0, calculator.viewResult()) t.is(42, calculator.viewResult(3)) diff --git a/spec/regression/received.spec.ts b/spec/regression/received.spec.ts index ad8633b..8b6b112 100644 --- a/spec/regression/received.spec.ts +++ b/spec/regression/received.spec.ts @@ -13,24 +13,24 @@ test('calling a method twice correctly asserts the call count', t => { calculator.add(1, 1) calculator.add(1, 1) - calculator[received](2).add(1, 1) - calculator[received]().add(1, 1) - t.throws(() => calculator[received](0).add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](2).add(1, 0), { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().add(1, 0), { instanceOf: SubstituteException }) + calculator.received(2).add(1, 1) + calculator.received().add(1, 1) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) }) test('calling a method twice correctly asserts the call count each time', t => { const calculator = Substitute.for() calculator.add(1, 1) - calculator[received](1).add(1, 1) + calculator.received(1).add(1, 1) calculator.add(1, 1) - calculator[received](2).add(1, 1) + calculator.received(2).add(1, 1) - t.throws(() => calculator[received](1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) }) test('calling a method with optional arguments correctly asserts the call count', t => { @@ -39,16 +39,16 @@ test('calling a method with optional arguments correctly asserts the call count' calculator.multiply(1, 1) calculator.multiply(2, 1) - calculator[received](1).multiply(1) - calculator[received](1).multiply(1, 1) - calculator[received](0).multiply(2) - calculator[received](1).multiply(2, 1) + calculator.received(1).multiply(1) + calculator.received(1).multiply(1, 1) + calculator.received(0).multiply(2) + calculator.received(1).multiply(2, 1) - t.throws(() => calculator[received](0).multiply(1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](0).multiply(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](2).multiply(1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](2).multiply(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).multiply(2), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(0).multiply(1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(0).multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).multiply(1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).multiply(2), { instanceOf: SubstituteException }) }) test('getting a property twice correctly asserts the call count', t => { @@ -56,10 +56,10 @@ test('getting a property twice correctly asserts the call count', t => { calculator.isEnabled calculator.isEnabled - calculator[received](2).isEnabled - calculator[received]().isEnabled - t.throws(() => calculator[received](0).isEnabled, { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).isEnabled, { instanceOf: SubstituteException }) + calculator.received(2).isEnabled + calculator.received().isEnabled + t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) }) test('setting a property twice correctly asserts the call count', t => { @@ -70,50 +70,50 @@ test('setting a property twice correctly asserts the call count', t => { } runLogic(calculator) - calculator[received](2).isEnabled = true - calculator[received]().isEnabled = true - t.throws(() => calculator[received](0).isEnabled = true, { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).isEnabled = true, { instanceOf: SubstituteException }) - t.throws(() => calculator[received](2).isEnabled = false, { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().isEnabled = false, { instanceOf: SubstituteException }) + calculator.received(2).isEnabled = true + calculator.received().isEnabled = true + t.throws(() => calculator.received(0).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled = true, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).isEnabled = false, { instanceOf: SubstituteException }) + t.throws(() => calculator.received().isEnabled = false, { instanceOf: SubstituteException }) }) test('calling a method twice with mock correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.add(1, 1)[returns](2) + calculator.add(1, 1).returns(2) calculator.add(1, 1) calculator.add(1, 1) - calculator[received](2).add(1, 1) - calculator[received]().add(1, 1) - t.throws(() => calculator[received](0).add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).add(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received](2).add(1, 0), { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().add(1, 0), { instanceOf: SubstituteException }) + calculator.received(2).add(1, 1) + calculator.received().add(1, 1) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).add(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received(2).add(1, 0), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) }) test('calling a method with mock based on Arg correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.add(Arg.all())[returns](0) + calculator.add(Arg.all()).returns(0) calculator.add(1, 1) - calculator[received]().add(Arg.all()) - calculator[received]().add(Arg.any(), Arg.any()) - calculator[received]().add(Arg.any('number'), Arg.any('number')) - calculator[received]().add(1, 1) - t.throws(() => calculator[received]().add(1, 0), { instanceOf: SubstituteException }) + calculator.received().add(Arg.all()) + calculator.received().add(Arg.any(), Arg.any()) + calculator.received().add(Arg.any('number'), Arg.any('number')) + calculator.received().add(1, 1) + t.throws(() => calculator.received().add(1, 0), { instanceOf: SubstituteException }) }) test('getting a property twice with mock correctly asserts the call count', t => { const calculator = Substitute.for() - calculator.isEnabled[returns](true) + calculator.isEnabled.returns(true) calculator.isEnabled calculator.isEnabled - calculator[received](2).isEnabled - calculator[received]().isEnabled - t.throws(() => calculator[received](0).isEnabled, { instanceOf: SubstituteException }) - t.throws(() => calculator[received](1).isEnabled, { instanceOf: SubstituteException }) + calculator.received(2).isEnabled + calculator.received().isEnabled + t.throws(() => calculator.received(0).isEnabled, { instanceOf: SubstituteException }) + t.throws(() => calculator.received(1).isEnabled, { instanceOf: SubstituteException }) }) test('calling a method with Arg correctly asserts the call count with Arg', t => { @@ -121,9 +121,9 @@ test('calling a method with Arg correctly asserts the call count with Arg', t => const calculator = Substitute.for() calculator.add(Arg.all()) - calculator[received](1).add(Arg.all()) - calculator[received]().add(Arg.all()) - t.throws(() => calculator[received](0).add(1, 1), { instanceOf: SubstituteException }) + calculator.received(1).add(Arg.all()) + calculator.received().add(Arg.all()) + t.throws(() => calculator.received(0).add(1, 1), { instanceOf: SubstituteException }) }) test('calling a method does not interfere with other properties or methods call counts', t => { @@ -131,10 +131,10 @@ test('calling a method does not interfere with other properties or methods call const calculator = Substitute.for() calculator.add(1, 1) - calculator[received](0).multiply(1, 1) - calculator[received](0).multiply(Arg.all()) - calculator[received](0).isEnabled + calculator.received(0).multiply(1, 1) + calculator.received(0).multiply(Arg.all()) + calculator.received(0).isEnabled - t.throws(() => calculator[received]().multiply(1, 1), { instanceOf: SubstituteException }) - t.throws(() => calculator[received]().multiply(Arg.all()), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().multiply(1, 1), { instanceOf: SubstituteException }) + t.throws(() => calculator.received().multiply(Arg.all()), { instanceOf: SubstituteException }) }) \ No newline at end of file diff --git a/spec/regression/rejects.spec.ts b/spec/regression/rejects.spec.ts index ac6872b..016fa7b 100644 --- a/spec/regression/rejects.spec.ts +++ b/spec/regression/rejects.spec.ts @@ -10,21 +10,21 @@ interface Calculator { test('rejects a method with no arguments', async t => { const calculator = Substitute.for() - calculator.getMemory()[rejects](new Error('No memory')) + calculator.getMemory().rejects(new Error('No memory')) await t.throwsAsync(calculator.getMemory(), { instanceOf: Error, message: 'No memory' }) }) test('rejects a method with arguments', async t => { const calculator = Substitute.for() - calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8)[rejects](new Error('Wrong sequence!')) + calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8).rejects(new Error('Wrong sequence!')) await t.throwsAsync(calculator.heavyOperation(0, 1, 1, 2, 4, 5, 8), { instanceOf: Error, message: 'Wrong sequence!' }) }) test('rejects different values in the specified order on a method', async t => { const calculator = Substitute.for() - calculator.heavyOperation(Arg.any('number'))[rejects](new Error('Wrong!'), new Error('Wrong again!')) + calculator.heavyOperation(Arg.any('number')).rejects(new Error('Wrong!'), new Error('Wrong again!')) await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong!' }) await t.throwsAsync(calculator.heavyOperation(0), { instanceOf: Error, message: 'Wrong again!' }) @@ -33,14 +33,14 @@ test('rejects different values in the specified order on a method', async t => { test('rejects a property', async t => { const calculator = Substitute.for() - calculator.model[rejects](new Error('No model')) + calculator.model.rejects(new Error('No model')) await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }) }) test('rejects different values in the specified order on a property', async t => { const calculator = Substitute.for() - calculator.model[rejects](new Error('No model'), new Error('I said "no model"')) + calculator.model.rejects(new Error('No model'), new Error('I said "no model"')) await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'No model' }) await t.throwsAsync(calculator.model, { instanceOf: Error, message: 'I said "no model"' }) diff --git a/spec/regression/resolves.spec.ts b/spec/regression/resolves.spec.ts index 87125cb..10fe86b 100644 --- a/spec/regression/resolves.spec.ts +++ b/spec/regression/resolves.spec.ts @@ -10,21 +10,21 @@ interface Calculator { test('resolves a method with no arguments', async t => { const calculator = Substitute.for() - calculator.getMemory()[resolves](0) + calculator.getMemory().resolves(0) t.is(await calculator.getMemory(), 0) }) test('resolves a method with arguments', async t => { const calculator = Substitute.for() - calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8)[resolves](13) + calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8).resolves(13) t.is(await calculator.heavyOperation(0, 1, 1, 2, 3, 5, 8), 13) }) test('resolves different values in the specified order on a method', async t => { const calculator = Substitute.for() - calculator.heavyOperation(Arg.any('number'))[resolves](1, 2, 3) + calculator.heavyOperation(Arg.any('number')).resolves(1, 2, 3) t.is(await calculator.heavyOperation(0), 1) t.is(await calculator.heavyOperation(0), 2) @@ -34,14 +34,14 @@ test('resolves different values in the specified order on a method', async t => test('resolves a property', async t => { const calculator = Substitute.for() - calculator.model[resolves]('Casio FX-82') + calculator.model.resolves('Casio FX-82') t.is(await calculator.model, 'Casio FX-82') }) test('resolves different values in the specified order on a property', async t => { const calculator = Substitute.for() - calculator.model[resolves]('Casio FX-82', 'TI-84 Plus') + calculator.model.resolves('Casio FX-82', 'TI-84 Plus') t.is(await calculator.model, 'Casio FX-82') t.is(await calculator.model, 'TI-84 Plus') diff --git a/spec/regression/returns.spec.ts b/spec/regression/returns.spec.ts index d076c04..068412b 100644 --- a/spec/regression/returns.spec.ts +++ b/spec/regression/returns.spec.ts @@ -18,10 +18,7 @@ interface Calculator { test('returns a primitive value for method with no arguments', t => { const calculator = Substitute.for() - calculator.clear()[returns]() - // calculator.add(1, 2).toExponential() - // calculator.isEnabled2.viewResult().returns(3) - // calculator.other().viewResult().returns(2) + calculator.clear().returns() t.is(void 0 as void, calculator.clear()) }) @@ -30,7 +27,7 @@ test('returns a primitive value for method with specific arguments', t => { const calculator = Substitute.for() const noResult = calculator.add(1, 1) - calculator.add(1, 1)[returns](2) + calculator.add(1, 1).returns(2) t.is(2, calculator.add(1, 1)) t.is(2, calculator.add(1, 1)) @@ -40,10 +37,10 @@ test('returns a primitive value for method with specific arguments', t => { test('returns a primitive value for method with specific arguments where the last argument is optional', t => { const calculator = Substitute.for() - calculator.multiply(2)[returns](4) - calculator.multiply(0, Arg.any('number'))[returns](0) - calculator.multiply(1, Arg.any())[returns](10) - calculator.multiply(1)[returns](1) + calculator.multiply(2).returns(4) + calculator.multiply(0, Arg.any('number')).returns(0) + calculator.multiply(1, Arg.any()).returns(10) + calculator.multiply(1).returns(1) t.is(4, calculator.multiply(2)) t.is(0, calculator.multiply(0, 10)) @@ -59,10 +56,10 @@ test('returns a primitive value for method with specific arguments where the las test('returns a primitive value for method with specific and conditional arguments', t => { const calculator = Substitute.for() - calculator.add(0, 0)[returns](0) - calculator.add(1, Arg.is((input: number) => input === 1))[returns](2) - calculator.add(2, Arg.any('number'))[returns](10) - calculator.add(Arg.is((input: number) => input > 2), Arg.any('number'))[returns](42) + calculator.add(0, 0).returns(0) + calculator.add(1, Arg.is((input: number) => input === 1)).returns(2) + calculator.add(2, Arg.any('number')).returns(10) + calculator.add(Arg.is((input: number) => input > 2), Arg.any('number')).returns(42) const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100), calculator.add(42, 84)] @@ -72,7 +69,7 @@ test('returns a primitive value for method with specific and conditional argumen test('returns a primitive value for method with Arg.all', t => { // #25: call verification does not work when using Arg.all() to set up return values https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/25 const calculator = Substitute.for() - calculator.add(Arg.all())[returns](42) + calculator.add(Arg.all()).returns(42) const results = [calculator.add(0, 0), calculator.add(1, 1), calculator.add(2, 100)] @@ -82,8 +79,8 @@ test('returns a primitive value for method with Arg.all', t => { test('returns a primitive value for method with one optional argument', t => { // #24: Mocked method arguments not allowed when verifying method was called https://github.com/ffMathy/FluffySpoon.JavaScript.Testing.Faking/issues/24 const calculator = Substitute.for() - calculator.viewResult()[returns](0) - calculator.viewResult(3)[returns](123) + calculator.viewResult().returns(0) + calculator.viewResult(3).returns(123) t.is(0, calculator.viewResult()) t.is(123, calculator.viewResult(3)) @@ -91,14 +88,14 @@ test('returns a primitive value for method with one optional argument', t => { test('returns a promise for method with no arguments', async t => { const calculator = Substitute.for() - calculator.getMemory()[returns](Promise.resolve(42)) + calculator.getMemory().returns(Promise.resolve(42)) t.is(await calculator.getMemory(), 42) }) test('returns a promise for method with specific arguments', async t => { const calculator = Substitute.for() - calculator.heavyOperation(1, 1)[returns](Promise.resolve(true)) + calculator.heavyOperation(1, 1).returns(Promise.resolve(true)) const result = await calculator.heavyOperation(1, 1) const noResult = calculator.heavyOperation(1, 1, 1) @@ -109,9 +106,9 @@ test('returns a promise for method with specific arguments', async t => { test('returns a promise for method with specific and conditional arguments', async t => { const calculator = Substitute.for() - calculator.heavyOperation(0)[returns](Promise.resolve(true)) - calculator.heavyOperation(1, Arg.is((input: number) => input === 1))[returns](Promise.resolve(false)) - calculator.heavyOperation(2, Arg.any('number'), 100)[returns](Promise.resolve(true)) + calculator.heavyOperation(0).returns(Promise.resolve(true)) + calculator.heavyOperation(1, Arg.is((input: number) => input === 1)).returns(Promise.resolve(false)) + calculator.heavyOperation(2, Arg.any('number'), 100).returns(Promise.resolve(true)) const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(1, 1), calculator.heavyOperation(2, 4321, 100)]) @@ -120,7 +117,7 @@ test('returns a promise for method with specific and conditional arguments', asy test('returns a promise for method with Arg.all', async t => { const calculator = Substitute.for() - calculator.heavyOperation(Arg.all())[returns](Promise.resolve(true)) + calculator.heavyOperation(Arg.all()).returns(Promise.resolve(true)) const results = await Promise.all([calculator.heavyOperation(0), calculator.heavyOperation(4321, 11, 42, 1234), calculator.heavyOperation(-1, 444)]) @@ -129,7 +126,7 @@ test('returns a promise for method with Arg.all', async t => { test('returns different primitive values in the specified order for method with arguments', t => { const calculator = Substitute.for() - calculator.add(1, Arg.any())[returns](1, NaN) + calculator.add(1, Arg.any()).returns(1, NaN) t.is(1, calculator.add(1, 1)) t.is(NaN, calculator.add(1, 0)) @@ -140,8 +137,8 @@ test('returns different primitive values in the specified order for method with test('returns another substituted instance for method with arguments', t => { const calculator = Substitute.for() const addResult = Substitute.for() - addResult.toLocaleString()[returns]('What a weird number') - calculator.add(1, Arg.any())[returns](addResult) + addResult.toLocaleString().returns('What a weird number') + calculator.add(1, Arg.any()).returns(addResult) const result = calculator.add(1, 1) @@ -154,7 +151,7 @@ test('returns a primitive value on a property', t => { const calculator = Substitute.for() const noResult = calculator.isEnabled - calculator.isEnabled[returns](true) + calculator.isEnabled.returns(true) t.true(calculator.isEnabled) t.true(calculator.isEnabled) @@ -163,14 +160,14 @@ test('returns a primitive value on a property', t => { test('returns a promise on a property', async t => { const calculator = Substitute.for() - calculator.model[returns](Promise.resolve('Casio FX-82')) + calculator.model.returns(Promise.resolve('Casio FX-82')) t.is(await calculator.model, 'Casio FX-82') }) test('returns different primitive values in the specified order on a property', t => { const calculator = Substitute.for() - calculator.isEnabled[returns](false, true) + calculator.isEnabled.returns(false, true) t.is(false, calculator.isEnabled) t.is(true, calculator.isEnabled) @@ -180,8 +177,8 @@ test('returns different primitive values in the specified order on a property', test('returns another substituted instance on a property', async t => { const calculator = Substitute.for() const modelResult = Substitute.for() - modelResult.replace(Arg.all())[returns]('TI-83') - calculator.model[returns](Promise.resolve(modelResult)) + modelResult.replace(Arg.all()).returns('TI-83') + calculator.model.returns(Promise.resolve(modelResult)) const result = await calculator.model t.is(result, modelResult) diff --git a/spec/regression/throws.spec.ts b/spec/regression/throws.spec.ts index 1396b29..eac673d 100644 --- a/spec/regression/throws.spec.ts +++ b/spec/regression/throws.spec.ts @@ -12,22 +12,22 @@ interface Calculator { test('throws on a method with arguments', t => { const calculator = Substitute.for() - calculator.divide(Arg.any(), 0)[throws](new Error('Cannot divide by 0')) + calculator.divide(Arg.any(), 0).throws(new Error('Cannot divide by 0')) t.throws(() => calculator.divide(1, 0), { instanceOf: Error, message: 'Cannot divide by 0' }) }) test('throws on a property being called', t => { const calculator = Substitute.for() - calculator.mode[throws](new Error('Property not set')) + calculator.mode.throws(new Error('Property not set')) t.throws(() => calculator.mode, { instanceOf: Error, message: 'Property not set' }) }) test('does not throw on methods that do not match arguments', t => { const calculator = Substitute.for() - calculator.divide(Arg.any(), 0)[throws](new Error('Cannot divide by 0')) - calculator.divide(4, 2)[returns](2) + calculator.divide(Arg.any(), 0).throws(new Error('Cannot divide by 0')) + calculator.divide(4, 2).returns(2) t.is(2, calculator.divide(4, 2)) t.throws(() => calculator.divide(1, 0), { instanceOf: Error, message: 'Cannot divide by 0' }) @@ -35,8 +35,8 @@ test('does not throw on methods that do not match arguments', t => { test('can set multiple throws for same method with different arguments', t => { const calculator = Substitute.for() - calculator.divide(Arg.any(), 0)[throws](new Error('Cannot divide by 0')) - calculator.divide(Arg.any(), Arg.is(number => !Number.isInteger(number)))[throws](new Error('Only integers supported')) + calculator.divide(Arg.any(), 0).throws(new Error('Cannot divide by 0')) + calculator.divide(Arg.any(), Arg.is(number => !Number.isInteger(number))).throws(new Error('Only integers supported')) t.throws(() => calculator.divide(1, 1.135), { instanceOf: Error, message: 'Only integers supported' }) t.throws(() => calculator.divide(1, 0), { instanceOf: Error, message: 'Cannot divide by 0' }) diff --git a/src/Substitute.ts b/src/Substitute.ts index c604436..3e211df 100644 --- a/src/Substitute.ts +++ b/src/Substitute.ts @@ -3,15 +3,9 @@ import { SubstituteNode } from './SubstituteNode' export type SubstituteOf = ObjectSubstitute & T -type InstantiableSubstitute> = T & { [SubstituteNode.instance]: SubstituteNode } - export class Substitute { public static for(): SubstituteOf { const substitute = SubstituteNode.createRoot() return substitute.proxy as unknown as SubstituteOf } - - private static extractSubstituteNodeFromSubstitute(substitute: InstantiableSubstitute>): SubstituteNode { - return substitute[SubstituteNode.instance] - } } \ No newline at end of file diff --git a/src/SubstituteNode.ts b/src/SubstituteNode.ts index 49cbdf3..9a98023 100644 --- a/src/SubstituteNode.ts +++ b/src/SubstituteNode.ts @@ -2,16 +2,17 @@ import { inspect, InspectOptions, types } from 'util' import { SubstituteNodeBase } from './SubstituteNodeBase' import { RecordedArguments } from './RecordedArguments' -import { PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier, isConfigurationMethod } from './Utilities' +import { PropertyType as PropertyTypeMap, isAssertionMethod, isSubstituteMethod, isSubstitutionMethod, textModifier, isConfigurationMethod, isThrowsFunction, isMimicksFunction, isResolvesFunction, isRejectsFunction, isReturnsFunction } from './Utilities' import { SubstituteException } from './SubstituteException' import type { SubstituteContext, SubstitutionMethod, PropertyType } from './Types' -import type { ObjectSubstitute } from './Transformations' +import type { ObjectSubstitute, OmitProxyMethods } from './Transformations' import { didNotReceive, mimick, mimicks, received, rejects, resolves, returns, throws, clearReceivedCalls } from './Transformations' -const instance = Symbol('Substitute:Instance') +export const instance = Symbol('Substitute:Instance') type SpecialProperty = typeof instance | typeof inspect.custom | 'then' -type RootContext = { substituteMethodsEnabled: boolean } + +type RootContext = { } export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitute { private _proxy: SubstituteNode @@ -27,7 +28,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private constructor(key: PropertyKey, parent?: SubstituteNode) { super(key, parent) if (this.isRoot()) { - this._rootContext = { substituteMethodsEnabled: true } + this._rootContext = { } } else { this._rootContext = this.root.rootContext @@ -37,21 +38,29 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu this, { get: function (target, property) { - if (target.isSpecialProperty(property)) + if (target.isSpecialProperty(property)) { + // console.log('specialProperty', property) return target.evaluateSpecialProperty(property) + } - if (target._retrySubstitutionExecutionAttempt) + if (target._retrySubstitutionExecutionAttempt) { + // console.log('reattemptSubstitutionExecution', property) return target.reattemptSubstitutionExecution()[property] + } const newNode = SubstituteNode.createChild(property, target) - if (target.isAssertion) + if (target.isAssertion) { + // console.log('executeAssertion', property); newNode.executeAssertion() + } - if (target.isRoot() && target.rootContext.substituteMethodsEnabled && (isAssertionMethod(property) || isConfigurationMethod(property))) { + if (target.isRoot() && (isAssertionMethod(property) || isConfigurationMethod(property))) { + // console.log("isRoot", property); newNode.assignContext(property) return newNode[property].bind(newNode) } + // console.log("substitutionExecution", property); return newNode.attemptSubstitutionExecution() }, set: function (target, property, value) { @@ -65,12 +74,19 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu apply: function (target, _thisArg, rawArguments) { target.handleMethod(rawArguments) if (target.hasDepthOfAtLeast(2)) { - if (isSubstitutionMethod(target.property)) + if (isSubstitutionMethod(target.property)) { + // console.log('isSubstitutionMethod', target.property) return target.parent.assignContext(target.property) + } - if (target.parent.isAssertion) + if (target.parent.isAssertion) { + // console.log('target.parent.isAssertion') return target.executeAssertion() + } } + + // console.log('target.isAssertion', target.isAssertion) + return target.isAssertion ? target.proxy : target.attemptSubstitutionExecution() @@ -79,7 +95,21 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu ) } - public static instance: typeof instance = instance + public received(amount?: number | undefined) { + return this[received](amount); + } + + public didNotReceive() { + return this[didNotReceive](); + } + + public mimick(instance: OmitProxyMethods) { + return this[mimick](instance); + } + + public clearReceivedCalls() { + return this[clearReceivedCalls](); + } public static createRoot(): SubstituteNode { return new this('*Substitute') @@ -139,7 +169,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu return this.proxy } - public [mimick]() { + public [mimick](_instance: OmitProxyMethods) { throw new Error('Mimick is not implemented yet') } @@ -169,6 +199,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private attemptSubstitutionExecution(): SubstituteNode | any { const mostSuitableSubstitution = this.getMostSuitableSubstitution() + // console.log('mostSuitableSubstitution', mostSuitableSubstitution) return mostSuitableSubstitution instanceof SubstituteNode ? mostSuitableSubstitution.executeSubstitution(this.recordedArguments) : this.proxy @@ -186,11 +217,11 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu ? this.child.recordedArguments.value?.shift() : this.child.recordedArguments.value[0] - if (substitutionMethod === throws) { + if (isThrowsFunction(substitutionMethod)) { throw substitutionValue; } - if (substitutionMethod === mimicks) { + if (isMimicksFunction(substitutionMethod)) { if (this.propertyType === PropertyTypeMap.Property) return substitutionValue() @@ -200,32 +231,33 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu return substitutionValue(...contextArguments.value) } - if (substitutionMethod === resolves) { + if (isResolvesFunction(substitutionMethod)) { return Promise.resolve(substitutionValue) } - if (substitutionMethod === rejects) { + if (isRejectsFunction(substitutionMethod)) { return Promise.reject(substitutionValue) } - if (substitutionMethod === returns) { + if (isReturnsFunction(substitutionMethod)) { return substitutionValue } - throw SubstituteException.generic(`Substitution method '${substitutionMethod}' not implemented. Make sure you invoke ".returns(...)" or any other configuration call on the given method.`) + throw SubstituteException.generic(`Substitution method '${String(substitutionMethod)}' not implemented. Make sure you invoke ".returns(...)" or any other configuration call on the given method.`) } private executeAssertion(): void | never { if (!this.hasDepthOfAtLeast(2)) - throw new Error('Not possible') + throw new Error('Depth is less than 2') if (!this.parent.recordedArguments.hasArguments()) - throw new TypeError('Parent args') + throw new Error('No parent args present') const expectedCount = this.parent.recordedArguments.value[0] ?? undefined const finiteExpectation = expectedCount !== undefined - if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) - throw new Error('Expected count has to be a positive integer') + if (finiteExpectation && (!Number.isInteger(expectedCount) || expectedCount < 0)) { + return + } const siblings = [...this.getAllSiblings().filter(n => !n.hasContext && n.accessorType === this.accessorType)] const hasBeenCalled = siblings.length > 0 @@ -283,6 +315,7 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu private handleMethod(rawArguments: any[]): void { this._propertyType = PropertyTypeMap.Method this._recordedArguments = RecordedArguments.from(rawArguments) + // console.log('handleMethod', rawArguments); } private getMostSuitableSubstitution(): SubstituteNode | void { @@ -306,12 +339,12 @@ export class SubstituteNode extends SubstituteNodeBase implements ObjectSubstitu } private isSpecialProperty(property: PropertyKey): property is SpecialProperty { - return property === SubstituteNode.instance || property === inspect.custom || property === 'then' + return property === instance || property === inspect.custom || property === 'then' } private evaluateSpecialProperty(property: SpecialProperty) { switch (property) { - case SubstituteNode.instance: + case instance: return this case inspect.custom: diff --git a/src/Transformations.ts b/src/Transformations.ts index 74291dd..dbad376 100644 --- a/src/Transformations.ts +++ b/src/Transformations.ts @@ -1,17 +1,27 @@ import type { AllArguments } from './Arguments'; import type { FirstLevelMethod } from './Types'; +import { Prettify } from './Utilities'; export const received = Symbol('received'); export const didNotReceive = Symbol('didNotReceive'); export const mimick = Symbol('mimick'); export const clearReceivedCalls = Symbol('clearReceivedCalls'); - export const mimicks = Symbol('mimicks'); export const throws = Symbol('throws'); export const returns = Symbol('returns'); export const resolves = Symbol('resolves'); export const rejects = Symbol('rejects'); +export type ReceivedPropertyKey = typeof received | 'received'; +export type DidNotReceivePropertyKey = typeof didNotReceive | 'didNotReceive'; +export type MimickPropertyKey = typeof mimick | 'mimick'; +export type ClearReceivedCallsPropertyKey = typeof clearReceivedCalls | 'clearReceivedCalls'; +export type MimicksPropertyKey = typeof mimicks | 'mimicks'; +export type ThrowsPropertyKey = typeof throws | 'throws'; +export type ReturnsPropertyKey = typeof returns | 'returns'; +export type ResolvesPropertyKey = typeof resolves | 'resolves'; +export type RejectsPropertyKey = typeof rejects | 'rejects'; + type FunctionSubstituteWithOverloads = TFunc extends { (...args: infer A1): infer R1; @@ -52,59 +62,109 @@ type FunctionHandler = FunctionSubstitute export type FunctionSubstitute = - ((...args: TArguments) => (TReturnType & MockObjectMixin)) & - ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) - -export type NoArgumentFunctionSubstitute = () => TReturnType & NoArgumentMockObjectMixin; -export type PropertySubstitute = TReturnType & NoArgumentMockObjectMixin; + ((...args: TArguments) => (TReturnType & MockObjectMixin)) & + ((allArguments: AllArguments) => (TReturnType & MockObjectMixin)) -type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; - -type MockObjectPromise = TReturnType extends Promise ? { - [resolves]: OneArgumentRequiredFunction; - [rejects]: OneArgumentRequiredFunction; -} : {} +export type NoArgumentFunctionSubstitute = + () => + TReturnType & + NoArgumentMockObjectMixin; -type BaseMockObjectMixin = MockObjectPromise & { - [returns]: OneArgumentRequiredFunction; - [throws]: OneArgumentRequiredFunction; -} +export type PropertySubstitute = + TReturnType & + NoArgumentMockObjectMixin; -type NoArgumentMockObjectMixin = BaseMockObjectMixin & { - [mimicks]: OneArgumentRequiredFunction<() => TReturnType, void>; -} +type OneArgumentRequiredFunction = (requiredInput: TArgs, ...restInputs: TArgs[]) => TReturnType; -type MockObjectMixin = BaseMockObjectMixin & { - [mimicks]: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void>; -} +type MockObjectPromise = TReturnType extends Promise ? ( + (TReturnType extends { resolves: any } ? + { [resolves]: OneArgumentRequiredFunction } : + { resolves: OneArgumentRequiredFunction }) & + (TReturnType extends { rejects: any } ? + { [rejects]: OneArgumentRequiredFunction } : + { rejects: OneArgumentRequiredFunction }) +) : {} + +type BaseMockObjectMixin = + MockObjectPromise & + ( + (TObject extends { returns: any } ? + { [returns]: OneArgumentRequiredFunction } : + { returns: OneArgumentRequiredFunction }) & + (TObject extends { throws: any } ? + { [throws]: OneArgumentRequiredFunction } : + { throws: OneArgumentRequiredFunction }) + ) + +type NoArgumentMockObjectMixin = + BaseMockObjectMixin & + (TObject extends { mimicks: any } ? + { [mimicks]: OneArgumentRequiredFunction<() => TReturnType, void> } : + { mimicks: OneArgumentRequiredFunction<() => TReturnType, void> }) + +type MockObjectMixin = + BaseMockObjectMixin & + (TReturnType extends { mimicks: any } ? + { [mimicks]: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void> } : + { mimicks: OneArgumentRequiredFunction<(...args: TArguments) => TReturnType, void> }) type TerminatingFunction = ((...args: TArguments) => void) & ((arg: AllArguments) => void) type TryToExpandNonArgumentedTerminatingFunction = - TObject[TProperty] extends (...args: []) => unknown ? () => void : {} + TObject[TProperty] extends (...args: []) => unknown ? + () => void : + {} + type TryToExpandArgumentedTerminatingFunction = - TObject[TProperty] extends (...args: any) => any ? FunctionSubstituteWithOverloads : {} + TObject[TProperty] extends (...args: any) => any ? + FunctionSubstituteWithOverloads : + {} type TerminatingObject = { - [P in keyof T]: TryToExpandNonArgumentedTerminatingFunction & TryToExpandArgumentedTerminatingFunction & T[P]; + [P in keyof T]: + TryToExpandNonArgumentedTerminatingFunction & + TryToExpandArgumentedTerminatingFunction & + T[P]; } type TryToExpandNonArgumentedFunctionSubstitute = - TObject[TProperty] extends (...args: []) => infer R ? NoArgumentFunctionSubstitute : {} + TObject[TProperty] extends (...args: []) => infer R ? + NoArgumentFunctionSubstitute : + {} type TryToExpandArgumentedFunctionSubstitute = - TObject[TProperty] extends (...args: infer F) => infer R ? F extends [] ? {} : FunctionSubstituteWithOverloads : {} + TObject[TProperty] extends (...args: infer F) => any ? + F extends [] ? + {} : + FunctionSubstituteWithOverloads : + {} -type TryToExpandPropertySubstitute = PropertySubstitute +type TryToExpandPropertySubstitute = + PropertySubstitute type ObjectSubstituteTransformation> = { - [P in keyof T]: TryToExpandNonArgumentedFunctionSubstitute & TryToExpandArgumentedFunctionSubstitute & TryToExpandPropertySubstitute; + [P in keyof T]: + TryToExpandNonArgumentedFunctionSubstitute & + TryToExpandArgumentedFunctionSubstitute & + TryToExpandPropertySubstitute; } export type OmitProxyMethods = Omit; -export type ObjectSubstitute = ObjectSubstituteTransformation & { - [received](amount?: number): TerminatingObject; - [didNotReceive](): TerminatingObject; - [mimick](instance: OmitProxyMethods): void; - [clearReceivedCalls](): void; -} \ No newline at end of file + +export type ObjectSubstitute = + ObjectSubstituteTransformation & + ObjectSubstituteMethods + +type ObjectSubstituteMethods = + (T extends { received: any } ? + { [received](amount?: number): TerminatingObject } : + { received(amount?: number): TerminatingObject }) & + (T extends { didNotReceive: any } ? + { [didNotReceive](): TerminatingObject } : + { didNotReceive(): TerminatingObject }) & + (T extends { mimick: any } ? + { [mimick](instance: OmitProxyMethods): void } : + { mimick(instance: OmitProxyMethods): void }) & + (T extends { clearReceivedCalls: any } ? + { [clearReceivedCalls](): void } : + { clearReceivedCalls(): void }) \ No newline at end of file diff --git a/src/Types.ts b/src/Types.ts index 5586edd..f655ccc 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -1,12 +1,26 @@ -import type { clearReceivedCalls, didNotReceive, mimick, mimicks, received, rejects, resolves, returns, throws } from "./Transformations" +import type { ClearReceivedCallsPropertyKey, DidNotReceivePropertyKey, MimickPropertyKey, MimicksPropertyKey, ReceivedPropertyKey, RejectsPropertyKey, ResolvesPropertyKey, ReturnsPropertyKey, ThrowsPropertyKey, clearReceivedCalls, didNotReceive, mimick, mimicks, received, rejects, resolves, returns, throws } from "./Transformations" export type PropertyType = 'method' | 'property' -export type AssertionMethod = typeof received | typeof didNotReceive -export type ConfigurationMethod = typeof clearReceivedCalls | typeof mimick -export type SubstitutionMethod = typeof mimicks | typeof throws | typeof returns | typeof resolves | typeof rejects + +export type AssertionMethod = + ReceivedPropertyKey | + DidNotReceivePropertyKey + +export type ConfigurationMethod = + ClearReceivedCallsPropertyKey | + MimickPropertyKey + +export type SubstitutionMethod = + MimicksPropertyKey | + ThrowsPropertyKey | + ReturnsPropertyKey | + ResolvesPropertyKey | + RejectsPropertyKey export type FirstLevelMethod = AssertionMethod | ConfigurationMethod + export type SubstituteMethod = FirstLevelMethod | SubstitutionMethod + export type SubstituteContext = SubstituteMethod | 'none' export type FilterFunction = (item: T) => boolean \ No newline at end of file diff --git a/src/Utilities.ts b/src/Utilities.ts index ade6596..406ae6d 100644 --- a/src/Utilities.ts +++ b/src/Utilities.ts @@ -1,7 +1,7 @@ import { inspect } from 'util' import { RecordedArguments } from './RecordedArguments' import type { AssertionMethod, ConfigurationMethod, SubstituteMethod, SubstitutionMethod } from './Types' -import { clearReceivedCalls, didNotReceive, mimick, mimicks, received, rejects, resolves, returns, throws } from './Transformations' +import { ClearReceivedCallsPropertyKey, DidNotReceivePropertyKey, MimickPropertyKey, MimicksPropertyKey, ReceivedPropertyKey, RejectsPropertyKey, ResolvesPropertyKey, ReturnsPropertyKey, ThrowsPropertyKey, clearReceivedCalls, didNotReceive, mimick, mimicks, received, rejects, resolves, returns, throws } from './Transformations' export const PropertyType = { Method: 'method', @@ -9,16 +9,24 @@ export const PropertyType = { } as const export const isAssertionMethod = (property: PropertyKey): property is AssertionMethod => - property === received || property === didNotReceive + isReceivedFunction(property) || + isDidNotReceiveFunction(property) export const isConfigurationMethod = (property: PropertyKey): property is ConfigurationMethod => - property === clearReceivedCalls || property === mimick + isClearReceivedCallsFunction(property) || + isMimickFunction(property) export const isSubstitutionMethod = (property: PropertyKey): property is SubstitutionMethod => - property === mimicks || property === returns || property === throws || property === resolves || property === rejects + isMimicksFunction(property) || + isReturnsFunction(property) || + isThrowsFunction(property) || + isResolvesFunction(property) || + isRejectsFunction(property) export const isSubstituteMethod = (property: PropertyKey): property is SubstituteMethod => - isSubstitutionMethod(property) || isConfigurationMethod(property) || isAssertionMethod(property) + isSubstitutionMethod(property) || + isConfigurationMethod(property) || + isAssertionMethod(property) export const stringifyArguments = (args: RecordedArguments) => textModifier.faint( args.hasArguments() ? @@ -27,7 +35,8 @@ export const stringifyArguments = (args: RecordedArguments) => textModifier.fain ) export const stringifyCalls = (calls: RecordedArguments[]) => { - if (calls.length === 0) return ' (no calls)' + if (calls.length === 0) + return ' (no calls)' const key = '\n-> call with ' const callsDetails = calls.map(stringifyArguments) @@ -41,4 +50,45 @@ export const textModifier = { italic: (str: string) => baseTextModifier(str, 3, 23) } -export const plurify = (str: string, count?: number) => `${str}${count === 1 ? '' : 's'}` \ No newline at end of file +export const plurify = (str: string, count?: number) => `${str}${count === 1 ? '' : 's'}` + +export function isDidNotReceiveFunction(property: PropertyKey): property is DidNotReceivePropertyKey { + return property === didNotReceive || property === 'didNotReceive' +} + +export function isReceivedFunction(property: PropertyKey): property is ReceivedPropertyKey { + return property === received || property === 'received' +} + +export function isClearReceivedCallsFunction(property: PropertyKey): property is ClearReceivedCallsPropertyKey { + return property === clearReceivedCalls || property === 'clearReceivedCalls' +} + +export function isMimickFunction(property: PropertyKey): property is MimickPropertyKey { + return property === mimick || property === 'mimick' +} + +export function isRejectsFunction(property: PropertyKey): property is RejectsPropertyKey { + return property === rejects || property === 'rejects' +} + +export function isResolvesFunction(property: PropertyKey): property is ResolvesPropertyKey { + return property === resolves || property === 'resolves' +} + +export function isThrowsFunction(property: PropertyKey): property is ThrowsPropertyKey { + return property === throws || property === 'throws' +} + +export function isReturnsFunction(property: PropertyKey): property is ReturnsPropertyKey { + return property === returns || property === 'returns' +} + +export function isMimicksFunction(property: PropertyKey): property is MimicksPropertyKey { + return property === mimicks || property === 'mimicks' +} + +// https://www.totaltypescript.com/concepts/the-prettify-helper +export type Prettify = { + [K in keyof T]: T[K]; +} & {}; \ No newline at end of file