diff --git a/package-lock.json b/package-lock.json index fcf3619..965d929 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,76 +4,131 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bl": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", + "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", + "requires": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.0.tgz", + "integrity": "sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==" + }, + "cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "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==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } + "restore-cursor": "^4.0.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "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==", + "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==" + }, "commander": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", - "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==" + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } }, "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, "is-docker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", - "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==" + }, + "is-unicode-supported": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.1.0.tgz", + "integrity": "sha512-lDcxivp8TJpLG75/DpatAqNzOpDPSpED8XNtrpBHTdQ2InQ1PbW78jhwSxyxhhu+xbVSast2X38bwj8atwoUQA==" }, "is-wsl": { "version": "2.2.0", @@ -88,191 +143,166 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "log-symbols": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz", + "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==", + "requires": { + "chalk": "^5.0.0", + "is-unicode-supported": "^1.1.0" + }, + "dependencies": { + "chalk": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.0.tgz", + "integrity": "sha512-/duVOqst+luxCQRKEo4bNxinsOQtMP80ZYm7mMqzuh5PociNL0PvmHFvREJ9ueYL2TxlHjBcmLCdmocx9Vg+IQ==" + } + } + }, + "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==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, "node-notifier": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz", - "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-10.0.0.tgz", + "integrity": "sha512-ZTqP90y1eyb2xAZTa7j4AlAayTwh6cL8mn0nlJhLDq8itXGnJUmQGYOnpaMUvqZVfGo0vhU7KZ3HtDW6CT2SiQ==", "requires": { "growly": "^1.3.0", "is-wsl": "^2.2.0", - "semver": "^7.3.2", + "semver": "^7.3.5", "shellwords": "^0.1.1", - "uuid": "^8.3.0", + "uuid": "^8.3.2", "which": "^2.0.2" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, "ora": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.1.0.tgz", - "integrity": "sha512-9tXIMPvjZ7hPTbk8DFq1f7Kow/HU/pQYB60JbNq+QnGwcyhWVZaQ4hM9zQDEsPxw/muLpgiHSaumUZxCAmod/w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-6.0.1.tgz", + "integrity": "sha512-TDdKkKHdWE6jo/6pIa5U5AWcSVfpNRFJ8sdRJpioGNVPLAzZzHs/N+QhUfF7ZbyoC+rnDuNTKzeDJUbAza9g4g==", "requires": { - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.4.0", - "is-interactive": "^1.0.0", - "log-symbols": "^4.0.0", - "mute-stream": "0.0.8", - "strip-ansi": "^6.0.0", + "bl": "^5.0.0", + "chalk": "^4.1.2", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.6.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^1.1.0", + "log-symbols": "^5.0.0", + "strip-ansi": "^7.0.1", "wcwidth": "^1.0.1" }, "dependencies": { - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.4.0.tgz", - "integrity": "sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==" - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, - "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==", - "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==" - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "^1.0.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" - }, - "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "requires": { - "chalk": "^4.0.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "requires": { - "defaults": "^1.0.3" - } } } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } }, "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } }, "which": { "version": "2.0.2", @@ -281,6 +311,11 @@ "requires": { "isexe": "^2.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index f20c9c6..d393839 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,27 @@ { - "name": "node-moviedb-cli", - "version": "1.0.0", - "description": "Assembler School: Node.js MovieDB CLI", - "keywords": [ - "node.js", - "cli app", - "assembler school" - ], - "author": "Dani Lucaci ", - "license": "MIT", - "private": true, - "main": "src/moviedb.js", - "repository": { - "type": "git", - "url": "https://github.com/assembler-school/node-moviedb-cli.git" - }, - "scripts": {}, - "dependencies": { - "chalk": "^4.1.0", - "commander": "^6.1.0", - "dotenv": "^8.2.0", - "node-notifier": "^8.0.0", - "ora": "^5.1.0" - } + "type": "module", + "name": "node-moviedb-cli", + "version": "1.0.0", + "description": "Assembler School: Node.js MovieDB CLI", + "keywords": [ + "node.js", + "cli app", + "assembler school" + ], + "author": "Dani Lucaci ", + "license": "MIT", + "private": true, + "main": "src/app.js", + "repository": { + "type": "git", + "url": "https://github.com/assembler-school/node-moviedb-cli.git" + }, + "scripts": {}, + "dependencies": { + "chalk": "^5.0.0", + "commander": "^8.3.0", + "dotenv": "^10.0.0", + "node-notifier": "^10.0.0", + "ora": "^6.0.1" + } } diff --git a/src/app.js b/src/app.js new file mode 100644 index 0000000..45a01e4 --- /dev/null +++ b/src/app.js @@ -0,0 +1,138 @@ +import { config } from "dotenv"; + +config(); + +import { Command } from "commander"; +import { default as ora } from "ora"; +import { getPerson, getPersons } from "./models/personModel.js"; +import { getMovie, getMovieReviews, getPlayingMovies, getPopularMovies } from "./models/movieModel.js"; +import { showPerson, showPersons } from "./views/personView.js"; +import { showMovie, showMovieReviews, showMovies } from "./views/movieView.js"; +import { optionParseInteger } from "./utils/option.js"; + +const program = new Command(); + +program.version("0.0.1", "-v, --version", "Display the current version"); + +program + .command("get-person") + .description("Make a network request to fetch most popular persons") + .requiredOption("-i, --id ", "The id of the person", optionParseInteger) + .action(async (options) => { + const { id } = options; + const loader = ora({ + text: "Fetching person details...", + spinner: "dots", + }); + + try { + loader.start(); + + const data = await getPerson(id); + + if (data.status_message) throw new Error(data.status_message); + + showPerson(data); + + loader.succeed("Person details loaded successfully"); + } catch (error) { + loader.fail(error.message); + } + }); + +program + .command("get-persons") + .description("Make a network request to fetch most popular persons") + .requiredOption("-p, --popular", "Fetch the popular persons") + .requiredOption("--page ", "The page of persons data results to fetch", optionParseInteger) + .action(async (options) => { + const { page } = options; + const loader = ora({ + text: "Fetching popular persons' data...", + spinner: "dots", + }); + + try { + loader.start(); + + const data = await getPersons(page); + + if (data.status_message) throw new Error(data.status_message); + + showPersons(data); + + loader.succeed("Popular persons' data loaded successfully"); + } catch (error) { + loader.fail(error.message); + } + }); + +program + .command("get-movies") + .description("Make a network request to fetch movies") + .requiredOption("--page ", "The page of movies data results to fetch", optionParseInteger) + .option("-p, --popular", "Fetch the popular movies") + .option("-n, --now-playing", "Fetch the movies that are playing now") + .action(async (options) => { + const { page, nowPlaying } = options; + const loader = ora({ + text: "Fetching the movies data...", + spinner: "dots", + }); + + try { + loader.start(); + + const data = nowPlaying ? await getPlayingMovies(page) : await getPopularMovies(page); + + if (data.status_message) throw new Error(data.status_message); + + showMovies(data); + + loader.succeed( + nowPlaying ? " Movies playing now data loaded successfully" : "Popular movies data loaded successfully" + ); + } catch (error) { + loader.fail(error.message); + } + }); + +program + .command("get-movie") + .description("Make a network request to fetch movie details") + .requiredOption("-i, --id ", "The id of the person", optionParseInteger) + .option("--page ", "Fetch the movie reviews", optionParseInteger, 1) + .option("--reviews", "Fetch the movie reviews") + .action(async (options) => { + const { id, reviews, page } = options; + const loader = ora({ + text: "Fetching the movie data...", + spinner: "dots", + }); + + try { + loader.start(); + + if (reviews) { + const data = await getMovieReviews(id, page); + + if (data.status_message) throw new Error(data.status_message); + + showMovieReviews(data); + + loader.succeed("Movie reviews loaded successfully"); + } else { + const data = await getMovie(id); + + if (data.status_message) throw new Error(data.status_message); + + showMovie(data); + + loader.succeed("Movie details loaded successfully"); + } + } catch (error) { + loader.fail(error.message); + } + }); + +program.parse(process.argv); diff --git a/src/img/app-view.png b/src/img/app-view.png deleted file mode 100644 index 3974171..0000000 Binary files a/src/img/app-view.png and /dev/null differ diff --git a/src/models/movieModel.js b/src/models/movieModel.js new file mode 100644 index 0000000..ed88014 --- /dev/null +++ b/src/models/movieModel.js @@ -0,0 +1,47 @@ +import request from "../utils/request.js"; + +async function getMovie(id) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/movie/${id}?api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +async function getMovieReviews(id, page) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/movie/${id}/reviews?page=${page}&api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +async function getPopularMovies(page) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/movie/popular?page=${page}&api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +async function getPlayingMovies(page) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/movie/now_playing?page=${page}&api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +export { getMovie, getMovieReviews, getPopularMovies, getPlayingMovies }; diff --git a/src/models/personModel.js b/src/models/personModel.js new file mode 100644 index 0000000..6a2a68e --- /dev/null +++ b/src/models/personModel.js @@ -0,0 +1,25 @@ +import request from "../utils/request.js"; + +async function getPerson(id) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/person/${id}?api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +async function getPersons(page) { + const options = { + method: "GET", + hostname: process.env.API_BASE_URL, + path: `/${process.env.API_VERSION}/person/popular?page=${page}&api_key=${process.env.API_KEY}`, + maxRedirects: 20, + }; + + return await request(options); +} + +export { getPerson, getPersons }; diff --git a/src/moviedb.js b/src/moviedb.js deleted file mode 100755 index dd5591a..0000000 --- a/src/moviedb.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node - -const { Command } = require("commander"); - -const program = new Command(); -program.version("0.0.1"); - -program - .command("get-persons") - .description("Make a network request to fetch most popular persons") - .action(function handleAction() { - console.log("hello-world"); - }); - -program - .command("get-person") - .description("Make a network request to fetch the data of a single person") - .action(function handleAction() { - console.log("hello-world"); - }); - -program - .command("get-movies") - .description("Make a network request to fetch movies") - .action(function handleAction() { - console.log("hello-world"); - }); - -program - .command("get-movie") - .description("Make a network request to fetch the data of a single person") - .action(function handleAction() { - console.log("hello-world"); - }); - -// error on unknown commands - -program.parse(process.argv); diff --git a/src/utils/option.js b/src/utils/option.js new file mode 100644 index 0000000..facbd72 --- /dev/null +++ b/src/utils/option.js @@ -0,0 +1,11 @@ +import { InvalidArgumentError } from "commander"; + +function optionParseInteger(value) { + const number = parseInt(value); + + if (isNaN(number)) throw new InvalidArgumentError("Not an integer value."); + + return number; +} + +export { optionParseInteger }; diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..ad614d5 --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,25 @@ +import https from "https"; + +function request(options) { + return new Promise((resolve, reject) => { + let data = ""; + + const req = https.request(options, (res) => { + res.on("data", function (chunk) { + data += chunk; + }); + + res.on("end", function () { + resolve(JSON.parse(data)); + }); + + res.on("error", function (error) { + reject(error); + }); + }); + + req.end(); + }); +} + +export default request; diff --git a/src/views/movieView.js b/src/views/movieView.js new file mode 100644 index 0000000..43cd465 --- /dev/null +++ b/src/views/movieView.js @@ -0,0 +1,83 @@ +import chalk from "chalk"; + +function showMovies(data) { + const movies = data.results || []; + + console.log(); + + movies.forEach((movie) => { + const { id, title, release_date } = movie; + + console.log(chalk.white("----------------------------------------\n")); + console.log(chalk.white("Movie:\n")); + console.log(`ID: ${chalk.white(id)}`); + console.log(`Title: ${chalk.blue.bold(title)}`); + console.log(`Release date: ${chalk.white(release_date)}`); + console.log(); + }); +} + +function showMovie(data) { + const { id, title, release_date, runtime, vote_count, overview, genres, spoken_languages } = data; + + console.log(); + + console.log(chalk.white("----------------------------------------\n")); + console.log(chalk.white("Movie:\n")); + console.log(`ID: ${chalk.white(id)}`); + console.log(`Title: ${chalk.blue.bold(title)}`); + console.log(`Release date: ${chalk.white(release_date)}`); + console.log(`Runtime ${chalk.white(runtime)}`); + console.log(`Vote count: ${chalk.white(vote_count)}`); + console.log(`Overview: ${chalk.white(overview)}`); + console.log(); + + if (genres.length) { + console.log("Genres:\n"); + + genres.forEach((genre) => { + console.log(chalk.white(genre.name)); + }); + } else { + console.log(chalk.yellow("The movie doesn’t have a declared genre")); + } + + console.log(); + + if (spoken_languages.length) { + console.log("Languages:\n"); + + spoken_languages.forEach((spoken_language) => { + console.log(chalk.white(spoken_language.name)); + }); + } else { + console.log(chalk.yellow("The movie doesn’t have a declared language")); + } + + console.log(); +} + +function showMovieReviews(data) { + const { page, total_pages, results: reviews } = data; + + console.log(); + + if (reviews.length) { + console.log(chalk.white("----------------------------------------")); + console.log(chalk.white(`Page ${page}/${total_pages}`)); + + reviews.forEach((review) => { + const { author, content } = review; + const reviewText = content.length < 400 ? content : content.slice(0, 400) + "..."; + + console.log(chalk.white("----------------------------------------\n")); + console.log(`Author: ${chalk.blue.bold(author)}`); + console.log(`Content: ${chalk.white(reviewText)}`); + console.log(); + }); + } else { + console.log(chalk.yellow("The movie doesn’t have any reviews")); + } +} + +export { showMovie, showMovies, showMovieReviews }; diff --git a/src/views/personView.js b/src/views/personView.js new file mode 100644 index 0000000..d79abf9 --- /dev/null +++ b/src/views/personView.js @@ -0,0 +1,73 @@ +import chalk from "chalk"; + +function showPerson(data) { + const { + id, + name, + birthday, + place_of_birth: birthplace, + known_for_department: department, + biography, + also_known_as: aliases, + } = data; + + console.log(); + + console.log(chalk.white("----------------------------------------\n")); + console.log(`ID: ${chalk.white(id)}`); + console.log(`Name: ${chalk.blue.bold(name)}`); + console.log(`Birth: ${chalk.white(birthday)} ${chalk.gray("|")} ${chalk.white(birthplace)}`); + console.log(`Department: ${department === "Acting" ? chalk.magenta(department) : chalk.white(department)}`); + console.log(`Biography: ${chalk.blue.bold(biography)}`); + console.log(); + + if (aliases.length) { + console.log("Also known as:\n"); + + aliases.forEach((alias) => { + console.log(`${chalk.white(alias)}`); + }); + } else { + console.log(`${chalk.yellow(name)} doesn’t have any alternative names`); + } + + console.log(); +} + +function showPersons(data) { + const persons = data.results || []; + + console.log(); + + persons.forEach((person) => { + const { id, name, known_for_department: department, known_for } = person; + const movies = known_for.filter((item) => { + return item.title !== undefined; + }); + + console.log(chalk.white("----------------------------------------\n")); + + console.log(`ID: ${chalk.white(id)}`); + console.log(`Name: ${chalk.blue.bold(name)}`); + console.log(`Department: ${department === "Acting" ? chalk.magenta(department) : chalk.white(department)}`); + console.log(); + + if (movies.length) { + console.log("Appearing in movies:\n"); + + movies.forEach((movie) => { + const { id, title, release_date } = movie; + + console.log(`\t${chalk.white("Movie:")}\n`); + console.log(`\tID: ${chalk.white(id)}`); + console.log(`\tRelease date: ${chalk.white(release_date)}`); + console.log(`\tTitle: ${chalk.white(title)}`); + console.log(); + }); + } else { + console.log(chalk.yellow(`${name} doesn’t appear in any movie\n`)); + } + }); +} + +export { showPerson, showPersons };