From 4830d7edc662ac6fae11a4c598afd6d6ef27eaf1 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Thu, 7 Sep 2023 23:18:16 -0500 Subject: [PATCH 01/15] install inquirer to make fancy cli --- package.json | 1 + yarn.lock | 249 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 243 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index e594e38e..052c835c 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@ant-design/icons": "^4.7.0", "@aws-sdk/client-s3": "^3.178.0", "@aws-sdk/client-ses": "^3.180.0", + "@inquirer/prompts": "^3.0.4", "@next-auth/mongodb-adapter": "^1.0.4", "@types/escape-html": "^1.0.2", "@types/formidable": "^2.0.5", diff --git a/yarn.lock b/yarn.lock index 289c91f9..954f8263 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1201,6 +1201,124 @@ resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@inquirer/checkbox@^1.3.9": + version "1.3.9" + resolved "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-1.3.9.tgz" + integrity sha512-PQJ0XEijmoXxp7QBnUIiYvqx9YC4c/MyJY5UIDXzsyrSY56xuWyi95ggaKq4KMbcjXfxmXSwuqEYbzWu3hAFuQ== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/confirm@^2.0.10": + version "2.0.10" + resolved "https://registry.npmjs.org/@inquirer/confirm/-/confirm-2.0.10.tgz" + integrity sha512-P2B3LgCn26EfK9LeSGbi6WWNg/Q7ZTZYERZ2YRJtNaQC4dEXDWt5xDkgKEHXopBeaBXrlBpHQ7Lb3IdhvWnCfQ== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + chalk "^4.1.2" + +"@inquirer/core@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@inquirer/core/-/core-4.0.0.tgz" + integrity sha512-YBo2o6ijIatBU1l1ziByZeVF4YdzKQnYs8tBJ8SnysgmK3YYQz/L/w5w7QXs4OVnbzTWhXiC4mn9gQGbDihsPQ== + dependencies: + "@inquirer/type" "^1.1.2" + "@types/mute-stream" "^0.0.1" + "@types/node" "^20.5.6" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + cli-spinners "^2.9.0" + cli-width "^4.1.0" + figures "^3.2.0" + mute-stream "^1.0.0" + run-async "^3.0.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + +"@inquirer/editor@^1.2.8": + version "1.2.8" + resolved "https://registry.npmjs.org/@inquirer/editor/-/editor-1.2.8.tgz" + integrity sha512-DzvzhtLmkVEzfphCbEQz63IuTwmgpeSyyaKrHwCsKYr/eUaMLksQz33VrHbwYbsBq4oNm14OkikrVIMC/XhhPw== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + chalk "^4.1.2" + external-editor "^3.1.0" + +"@inquirer/expand@^1.1.9": + version "1.1.9" + resolved "https://registry.npmjs.org/@inquirer/expand/-/expand-1.1.9.tgz" + integrity sha512-8XuyeEVAEDCuDfK4+LVsOKfIOaC/Hen5nq+yMgyoQi4DgG77uLFtzjFBgOC0+HTEOugznF66DoWskUOmIN4x5Q== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/input@^1.2.9": + version "1.2.9" + resolved "https://registry.npmjs.org/@inquirer/input/-/input-1.2.9.tgz" + integrity sha512-FC/wnXklGwUcGtlOU67T3pKHu6l1L5tIOHbZcqoLTlsdG8ukNARrX8h9Xrdgfr29t/LbvSxqdvYRmn4u2XRz0Q== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + chalk "^4.1.2" + +"@inquirer/password@^1.1.9": + version "1.1.9" + resolved "https://registry.npmjs.org/@inquirer/password/-/password-1.1.9.tgz" + integrity sha512-6L/SimCHutKVPDjkJBAkGO0POdJA3VXbdgAhCsX9katuyQSiMq5WGGa2Nqv7zXqiZxL5YuTPFqNNKKq00Q1HxA== + dependencies: + "@inquirer/input" "^1.2.9" + "@inquirer/type" "^1.1.2" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + +"@inquirer/prompts@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-3.0.4.tgz#8e6f071fe2d9a8b5fe5a2c573add90758c443618" + integrity sha512-xSBQjaj0zKGb+o6MiTd/Igl609JOwFf/DyU0vyiFiFR7u65n8JgCFVWLSeOWEFUP8L+AOGxZolhvuJ8KgCxIrg== + dependencies: + "@inquirer/checkbox" "^1.3.9" + "@inquirer/confirm" "^2.0.10" + "@inquirer/core" "^4.0.0" + "@inquirer/editor" "^1.2.8" + "@inquirer/expand" "^1.1.9" + "@inquirer/input" "^1.2.9" + "@inquirer/password" "^1.1.9" + "@inquirer/rawlist" "^1.2.9" + "@inquirer/select" "^1.2.9" + +"@inquirer/rawlist@^1.2.9": + version "1.2.9" + resolved "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-1.2.9.tgz" + integrity sha512-HqZeTP/F0l9LE0uCSbPHUbxVjoh8TLPzy8+BJzXyS9Na+XbbMOGN7KVNkNEGY+GH7X05jdOtd4gsO9DtAJUM2Q== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + chalk "^4.1.2" + +"@inquirer/select@^1.2.9": + version "1.2.9" + resolved "https://registry.npmjs.org/@inquirer/select/-/select-1.2.9.tgz" + integrity sha512-WXMQfUGzxrxdbDCU50xKqYCMoz+SOZnyV8sOeEJ8Ei5AjANz1fap3xA7EF8aZLJ9K1//m4OnyS/XDoi31Tqn+g== + dependencies: + "@inquirer/core" "^4.0.0" + "@inquirer/type" "^1.1.2" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + figures "^3.2.0" + +"@inquirer/type@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@inquirer/type/-/type-1.1.2.tgz" + integrity sha512-lowHTIBAE/bltg7/EchMDLfKUdT0BCyS2xzqgjsyKADybz2QZ0cLWtDXzjT1C6rdZI07Ng9jU4d2R9rDoU+6Hw== + "@next-auth/mongodb-adapter@^1.0.4": version "1.0.4" resolved "https://registry.npmjs.org/@next-auth/mongodb-adapter/-/mongodb-adapter-1.0.4.tgz" @@ -1355,10 +1473,17 @@ dependencies: mongodb "*" -"@types/node@*": - version "18.0.0" - resolved "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz" - integrity sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA== +"@types/mute-stream@^0.0.1": + version "0.0.1" + resolved "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.1.tgz" + integrity sha512-0yQLzYhCqGz7CQPE3iDmYjhb7KMBFOP+tBkyw+/Y2YyDI5wpS7itXXxneN1zSsUwWx3Ji6YiVYrhAnpQGS/vkw== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@^20.5.6": + version "20.5.9" + resolved "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz" + integrity sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ== "@types/prop-types@*": version "15.7.5" @@ -1399,6 +1524,11 @@ "@types/node" "*" "@types/webidl-conversions" "*" +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@typescript-eslint/parser@^5.21.0": version "5.30.0" resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.0.tgz" @@ -1463,6 +1593,13 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" @@ -1475,7 +1612,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1700,7 +1837,7 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1708,11 +1845,26 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6, classnames@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz" integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== +cli-spinners@^2.9.0: + version "2.9.0" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz" + integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== + +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" @@ -1901,6 +2053,11 @@ dotenv@^16.0.2: resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz" integrity sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" @@ -2196,6 +2353,15 @@ export-to-csv@^0.2.1: resolved "https://registry.npmjs.org/export-to-csv/-/export-to-csv-0.2.1.tgz" integrity sha512-KTbrd3CAZ0cFceJEZr1e5uiMasabeCpXq1/5uvVxDl53o4jXJHnltasQoj2NkzrxD8hU9kdwjnMhoir/7nNx/A== +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" @@ -2239,6 +2405,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +figures@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" @@ -2458,6 +2631,13 @@ highlight-words-core@^1.2.0: resolved "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz" integrity sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg== +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" @@ -2547,6 +2727,11 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-fullwidth-code-point@^3.0.0: + 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== + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" @@ -2865,6 +3050,11 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz" @@ -3045,6 +3235,11 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" @@ -3717,6 +3912,11 @@ rrule@2.6.4: optionalDependencies: luxon "^1.21.3" +run-async@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz" + integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" @@ -3724,6 +3924,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + saslprep@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz" @@ -3828,6 +4033,15 @@ string-format@^2.0.0: resolved "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string.prototype.matchall@^4.0.7: version "4.0.7" resolved "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz" @@ -3860,7 +4074,7 @@ string.prototype.trimstart@^1.0.5: define-properties "^1.1.4" es-abstract "^1.19.5" -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -3921,6 +4135,13 @@ text-table@^0.2.0: resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" @@ -3989,6 +4210,11 @@ type-fest@^0.20.2: resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typescript@4.8.3: version "4.8.3" resolved "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz" @@ -4075,6 +4301,15 @@ wordwrapjs@^4.0.0: reduce-flatten "^2.0.0" typical "^5.2.0" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" From 93dc72483ffaac4d1c6089c1d2a53c992f9b7add Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Thu, 7 Sep 2023 23:18:39 -0500 Subject: [PATCH 02/15] implement cli draft --- scripts/dev-cli.ts | 101 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 scripts/dev-cli.ts diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts new file mode 100644 index 00000000..f54e2fa2 --- /dev/null +++ b/scripts/dev-cli.ts @@ -0,0 +1,101 @@ +import { input, select } from '@inquirer/prompts'; +import * as dotenv from 'dotenv'; +import application from '../models/application'; +dotenv.config(); + +/** + * NOTE: To use this CLI tool, run `ts-node scripts/dev-cli.ts` in your terminal. + */ +const executeCLI = async () => { + // Select database + const db = await select({ + message: 'Select database to perform action on', + choices: [ + { + name: 'Development Database', + value: 'dev-db', + }, + ], + }); + + // Select action + const action = await select({ + message: 'Select action to perform', + choices: [ + { + name: "Modify a hacker's document", + value: 'modify-hacker', + }, + ], + }); + + // Perform action + switch (action) { + case 'modify-hacker': + await handleModifyHacker(); + break; + default: + console.log('Invalid action'); + } +}; + +/** + * Quickly change the application status of hacker. + * A hacker has multiple application statuses. + */ +const handleModifyHacker = async () => { + const hackerEmail = await input({ + message: 'Enter hacker email', + }); + + const subAction1 = await select({ + message: 'Select sub-action to perform', + choices: [ + { + name: 'Change application status to CREATED', + value: 'created', + }, + { + name: 'Change application status to DECLINED', + value: 'declined', + }, + { + name: 'Change application status to SUBMITTED', + value: 'submitted', + }, + { + name: 'Change application status to ACCEPTED', + value: 'accepted', + }, + { + name: 'Change application status to CONFIRMED', + value: 'confirmed', + }, + { + name: 'Change application status to REJECTED', + value: 'rejected', + }, + { + name: 'Change application status to CHECKED_IN', + value: 'checked-in', + }, + ], + }); + + const subAction2 = await select({ + message: "Do you want to delete the hacker's application?", + choices: [ + { + name: 'Yes', + value: 'yes', + }, + { + name: 'No', + value: 'no', + }, + ], + }); +}; + +// Execute the CLI tool +executeCLI(); From 17f29cf7c8fc47ae4a890d8f61f7c7f368a83e0b Mon Sep 17 00:00:00 2001 From: Gabriel Dong Date: Sat, 9 Sep 2023 15:03:49 -0500 Subject: [PATCH 03/15] initial cli commit --- scripts/cli-util/get-hacker.ts | 57 +++++++++++++++ scripts/cli-util/modify-hacker.ts | 102 +++++++++++++++++++++++++++ scripts/dev-cli.ts | 113 +++++++++++++++--------------- 3 files changed, 216 insertions(+), 56 deletions(-) create mode 100644 scripts/cli-util/get-hacker.ts create mode 100644 scripts/cli-util/modify-hacker.ts diff --git a/scripts/cli-util/get-hacker.ts b/scripts/cli-util/get-hacker.ts new file mode 100644 index 00000000..e65da658 --- /dev/null +++ b/scripts/cli-util/get-hacker.ts @@ -0,0 +1,57 @@ +import { input, select } from '@inquirer/prompts'; +import { UserData } from '../../types/database'; +import useSWR from 'swr'; +import dbConnect from '../../middleware/database'; + +export const handleGetHacker = async () => { + const hackerEmail = await input({ + message: 'Enter hacker email', + }); + + const subAction1 = await select({ + message: 'Select an action to perform', + choices: [ + { + name: 'Get events', + value: 'get-events', + }, + { + name: 'Get team info', + value: 'get-team', + }, + { + name: 'Get application', + value: 'get-application', + }, + { + name: 'Get document', + value: 'get-document', + }, + ], + }); + + switch (subAction1) { + case 'get-events': + await getEvents(); + break; + case 'get-team': + await getTeam(); + break; + case 'get-application': + await getApplication(); + break; + case 'get-document': + await getDocument(); + break; + default: + console.log('Invalid action'); + } +}; + +const getEvents = async () => {}; + +const getTeam = async () => {}; + +const getApplication = async () => {}; + +const getDocument = async () => {}; diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts new file mode 100644 index 00000000..31cdd7f5 --- /dev/null +++ b/scripts/cli-util/modify-hacker.ts @@ -0,0 +1,102 @@ +import { input, select } from '@inquirer/prompts'; +import dbConnect from '../../middleware/database'; + +// TODO: zi +/** + * Quickly change the application status of hacker. + * A hacker has multiple application statuses. + */ +export const handleModifyHacker = async () => { + // get hacker email + const hackerEmail = await input({ + message: 'Enter hacker email', + }); + + // get sub-action + const subAction1 = await select({ + message: 'Select sub-action to perform', + choices: [ + { + name: 'Change application status', + value: 'change-status', + }, + { + name: 'Delete application', + value: 'delete-application', + }, + { + name: 'Join a team', + value: 'join-team', + }, + { + name: 'Leave team', + value: 'leave-team', + }, + { + name: 'NFC check-in', + value: 'nfc-check-in', + }, + ], + }); + + // perf + switch (subAction1) { + case 'change-status': + break; + case 'delete-application': + break; + case 'join-team': + break; + case 'leave-team': + break; + case 'nfc-check-in': + break; + } +}; + +const changeStatus = async () => { + const newStatus = await select({ + message: 'Select new status', + choices: [ + { + name: 'Change application status to CREATED', + value: 'created', + }, + { + name: 'Change application status to DECLINED', + value: 'declined', + }, + { + name: 'Change application status to SUBMITTED', + value: 'submitted', + }, + { + name: 'Change application status to ACCEPTED', + value: 'accepted', + }, + { + name: 'Change application status to CONFIRMED', + value: 'confirmed', + }, + { + name: 'Change application status to REJECTED', + value: 'rejected', + }, + { + name: 'Change application status to CHECKED_IN', + value: 'checked-in', + }, + ], + }); + + // + await dbConnect(); +}; + +const deleteApplication = async () => {}; + +const joinTeam = async () => {}; + +const leaveTeam = async () => {}; + +const nfcCheckIn = async () => {}; diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index f54e2fa2..81a97162 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -1,6 +1,9 @@ import { input, select } from '@inquirer/prompts'; +import dbConnect from '../middleware/database'; import * as dotenv from 'dotenv'; import application from '../models/application'; +import { handleModifyHacker } from './cli-util/modify-hacker'; +import { handleGetHacker } from './cli-util/get-hacker'; dotenv.config(); /** @@ -18,19 +21,70 @@ const executeCLI = async () => { ], }); + // TODO: + // list actions we as devs will need to do and can be simplified with this CLI tool + // [ ] populate collections with dummy data + // [ ] clear collection (danger) + // [G] get a document from a colleciton (i.e., hacker document using email) + // [ ] hacker document using email + // [ ] team document using team or hacker email or team invite code + // [Z] automatically allow a hacker to check in to an event (via nfc) + // Select action const action = await select({ message: 'Select action to perform', choices: [ + { + name: "Get a hacker's document", + value: 'get-hacker', + // sub-action: + // 1. see their events + // 2. see their team info + // 3. see their application + // 4. get entire JSON of their document + }, + { + name: 'Get a team document', + value: 'get-team', + // sub-action: + // 1. see their schedule + // 2. see their members + // 3. get entire JSON of their document + }, { name: "Modify a hacker's document", value: 'modify-hacker', + // sub-action: + // 1. change application status + // 2. delete application + // 3. join/leave team + // 4. check in + }, + { + name: 'Modify a team', + value: 'modify-team', + // sub-action: + // 1. change team name + // 2. change team members? + // 3. change team invite code? + // 4. change devpost link? + }, + { + name: 'Clear a collection (dangerous)', + value: 'clear-collection', + }, + { + name: 'Populate a collection', + value: 'populate-collection', }, ], }); // Perform action switch (action) { + case 'get-hacker': + await handleGetHacker(); + break; case 'modify-hacker': await handleModifyHacker(); break; @@ -39,62 +93,9 @@ const executeCLI = async () => { } }; -/** - * Quickly change the application status of hacker. - * A hacker has multiple application statuses. - */ -const handleModifyHacker = async () => { - const hackerEmail = await input({ - message: 'Enter hacker email', - }); - - const subAction1 = await select({ - message: 'Select sub-action to perform', - choices: [ - { - name: 'Change application status to CREATED', - value: 'created', - }, - { - name: 'Change application status to DECLINED', - value: 'declined', - }, - { - name: 'Change application status to SUBMITTED', - value: 'submitted', - }, - { - name: 'Change application status to ACCEPTED', - value: 'accepted', - }, - { - name: 'Change application status to CONFIRMED', - value: 'confirmed', - }, - { - name: 'Change application status to REJECTED', - value: 'rejected', - }, - { - name: 'Change application status to CHECKED_IN', - value: 'checked-in', - }, - ], - }); - - const subAction2 = await select({ - message: "Do you want to delete the hacker's application?", - choices: [ - { - name: 'Yes', - value: 'yes', - }, - { - name: 'No', - value: 'no', - }, - ], - }); +// handle api error(a function that's called when API calls return 404) +const handleError = () => { + console.log('Error: You need to have the witness running'); }; // Execute the CLI tool From 2935cfaf75a18aa0100063ed00597d2085566394 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Sat, 9 Sep 2023 15:39:26 -0500 Subject: [PATCH 04/15] implement GET and MODIFY for hacker document Co-authored-by: Gabriel Dong --- scripts/cli-util/get-hacker.ts | 31 +++++++++++++++++++++++-------- scripts/cli-util/modify-hacker.ts | 29 ++++++++++++++++++++++------- scripts/dev-cli.ts | 11 +++++++++++ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/scripts/cli-util/get-hacker.ts b/scripts/cli-util/get-hacker.ts index e65da658..a6c67c4d 100644 --- a/scripts/cli-util/get-hacker.ts +++ b/scripts/cli-util/get-hacker.ts @@ -1,18 +1,26 @@ import { input, select } from '@inquirer/prompts'; -import { UserData } from '../../types/database'; -import useSWR from 'swr'; import dbConnect from '../../middleware/database'; +import User from '../../models/user'; +import team from '../../models/team'; +import { promptAction } from '../dev-cli'; +import { UserData, TeamData } from '../../types/database'; export const handleGetHacker = async () => { const hackerEmail = await input({ message: 'Enter hacker email', }); + const user: UserData | null = JSON.parse(JSON.stringify(await User.findOne({ email: hackerEmail }))); + if (!user) { + console.log('Hacker not found'); + return promptAction(); + } + const subAction1 = await select({ message: 'Select an action to perform', choices: [ { - name: 'Get events', + name: 'Get events attended', value: 'get-events', }, { @@ -30,18 +38,21 @@ export const handleGetHacker = async () => { ], }); + // connect to db + await dbConnect(); + switch (subAction1) { case 'get-events': await getEvents(); break; case 'get-team': - await getTeam(); + await getTeam(user); break; case 'get-application': await getApplication(); break; case 'get-document': - await getDocument(); + console.log(user); break; default: console.log('Invalid action'); @@ -50,8 +61,12 @@ export const handleGetHacker = async () => { const getEvents = async () => {}; -const getTeam = async () => {}; +const getTeam = async (user: UserData) => { + const teamId = user.team; + const hackerTeam = JSON.parse(JSON.stringify(await team.findOne({ _id: teamId }))); + console.log(hackerTeam); -const getApplication = async () => {}; + return promptAction(); +}; -const getDocument = async () => {}; +const getApplication = async () => {}; diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index 31cdd7f5..ed3200d7 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -1,5 +1,7 @@ import { input, select } from '@inquirer/prompts'; -import dbConnect from '../../middleware/database'; +import User from '../../models/user'; +import { promptAction } from '../dev-cli'; +import { ApplicationStatus, UserData } from '../../types/database'; // TODO: zi /** @@ -12,8 +14,17 @@ export const handleModifyHacker = async () => { message: 'Enter hacker email', }); + // query for hacker document + const hacker: UserData | null = await User.findOne({ email: hackerEmail }); + + // if hacker not found, re-prompt + if (!hacker) { + console.log('Oops, Hacker not found! Please try again.'); + return promptAction(); + } + // get sub-action - const subAction1 = await select({ + const subAction = await select({ message: 'Select sub-action to perform', choices: [ { @@ -39,9 +50,10 @@ export const handleModifyHacker = async () => { ], }); - // perf - switch (subAction1) { + // perform sub-action + switch (subAction) { case 'change-status': + await changeStatus(hacker); break; case 'delete-application': break; @@ -54,7 +66,11 @@ export const handleModifyHacker = async () => { } }; -const changeStatus = async () => { +const changeStatus = async (hacker: UserData) => { + const oldStatus: ApplicationStatus = hacker.applicationStatus; + + // console.log(`Current status: ${Object.values(ApplicationStatus)[oldStatus]}`); + const newStatus = await select({ message: 'Select new status', choices: [ @@ -89,8 +105,7 @@ const changeStatus = async () => { ], }); - // - await dbConnect(); + // TODO: }; const deleteApplication = async () => {}; diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index 81a97162..27aba9e1 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -21,6 +21,17 @@ const executeCLI = async () => { ], }); + // connect to db + await dbConnect(process.env.DATABASE_URL); + + // prompt action + await promptAction(); + + // exit + process.exit(0); +}; + +export const promptAction = async () => { // TODO: // list actions we as devs will need to do and can be simplified with this CLI tool // [ ] populate collections with dummy data From 0e3e80eb3e343faf5362d0940c127d688e792fb6 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Wed, 13 Sep 2023 23:32:29 -0500 Subject: [PATCH 05/15] finish implement changeStatus for hacker doc --- scripts/cli-util/modify-hacker.ts | 48 ++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index ed3200d7..f6a3bd5f 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -68,44 +68,51 @@ export const handleModifyHacker = async () => { const changeStatus = async (hacker: UserData) => { const oldStatus: ApplicationStatus = hacker.applicationStatus; + const oldStatusString = getApplicationStatusString(oldStatus); - // console.log(`Current status: ${Object.values(ApplicationStatus)[oldStatus]}`); + console.log(`Current status: ${oldStatus} (${oldStatusString})`); - const newStatus = await select({ + const newStatus: ApplicationStatus = await select({ message: 'Select new status', choices: [ { name: 'Change application status to CREATED', - value: 'created', + value: ApplicationStatus.CREATED, }, { name: 'Change application status to DECLINED', - value: 'declined', + value: ApplicationStatus.DECLINED, + }, + { + name: 'Change application status to STARTED', + value: ApplicationStatus.STARTED, }, { name: 'Change application status to SUBMITTED', - value: 'submitted', + value: ApplicationStatus.SUBMITTED, }, { name: 'Change application status to ACCEPTED', - value: 'accepted', + value: ApplicationStatus.ACCEPTED, }, { name: 'Change application status to CONFIRMED', - value: 'confirmed', + value: ApplicationStatus.CONFIRMED, }, { name: 'Change application status to REJECTED', - value: 'rejected', + value: ApplicationStatus.REJECTED, }, { name: 'Change application status to CHECKED_IN', - value: 'checked-in', + value: ApplicationStatus.CHECKED_IN, }, ], }); - // TODO: + await User.updateOne({ email: hacker.email }, { applicationStatus: newStatus }); + + console.log(`Changed application status from ${oldStatus} to ${newStatus}`); }; const deleteApplication = async () => {}; @@ -115,3 +122,24 @@ const joinTeam = async () => {}; const leaveTeam = async () => {}; const nfcCheckIn = async () => {}; + +const getApplicationStatusString = (status: ApplicationStatus): string => { + switch (status) { + case ApplicationStatus.CREATED: + return 'CREATED'; + case ApplicationStatus.DECLINED: + return 'DECLINED'; + case ApplicationStatus.STARTED: + return 'STARTED'; + case ApplicationStatus.SUBMITTED: + return 'SUBMITTED'; + case ApplicationStatus.ACCEPTED: + return 'ACCEPTED'; + case ApplicationStatus.CONFIRMED: + return 'CONFIRMED'; + case ApplicationStatus.REJECTED: + return 'REJECTED'; + case ApplicationStatus.CHECKED_IN: + return 'CHECKED_IN'; + } +}; From 83a0e1ee21f562070c19786828a9ab189ee25bbf Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Wed, 13 Sep 2023 23:39:23 -0500 Subject: [PATCH 06/15] finish implement delete application for hacker doc --- scripts/cli-util/modify-hacker.ts | 45 ++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index f6a3bd5f..1f257b53 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -2,6 +2,7 @@ import { input, select } from '@inquirer/prompts'; import User from '../../models/user'; import { promptAction } from '../dev-cli'; import { ApplicationStatus, UserData } from '../../types/database'; +import Application from '../../models/application'; // TODO: zi /** @@ -56,6 +57,7 @@ export const handleModifyHacker = async () => { await changeStatus(hacker); break; case 'delete-application': + await deleteApplication(hacker); break; case 'join-team': break; @@ -67,11 +69,12 @@ export const handleModifyHacker = async () => { }; const changeStatus = async (hacker: UserData) => { + // get old status const oldStatus: ApplicationStatus = hacker.applicationStatus; const oldStatusString = getApplicationStatusString(oldStatus); - console.log(`Current status: ${oldStatus} (${oldStatusString})`); + // query for new status const newStatus: ApplicationStatus = await select({ message: 'Select new status', choices: [ @@ -110,12 +113,48 @@ const changeStatus = async (hacker: UserData) => { ], }); + // update hacker document and log await User.updateOne({ email: hacker.email }, { applicationStatus: newStatus }); - console.log(`Changed application status from ${oldStatus} to ${newStatus}`); + + return promptAction(); }; -const deleteApplication = async () => {}; +const deleteApplication = async (hacker: UserData) => { + // check if hacker has an application + if (!hacker.application) { + console.log('Hacker does not have an application'); + return; + } + + // confirm deletion + const confirm = await select({ + message: `Application Found! Are you sure you want to delete it (${hacker.application})?`, + choices: [ + { + name: 'Yes', + value: true, + }, + { + name: 'No', + value: false, + }, + ], + }); + + // cancel if not confirmed + if (!confirm) { + console.log('Cancelled'); + return promptAction(); + } + + // perform deletion and log + await Application.deleteOne({ _id: hacker.application }); + await User.updateOne({ email: hacker.email }, { application: null }); + console.log('Deleted application successfully'); + + return promptAction(); +}; const joinTeam = async () => {}; From 28e1ba8e2bac9c1ab4980b949942924c75c66670 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Wed, 13 Sep 2023 23:42:33 -0500 Subject: [PATCH 07/15] add quit option --- scripts/cli-util/modify-hacker.ts | 2 +- scripts/dev-cli.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index 1f257b53..d089e467 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -124,7 +124,7 @@ const deleteApplication = async (hacker: UserData) => { // check if hacker has an application if (!hacker.application) { console.log('Hacker does not have an application'); - return; + return promptAction(); } // confirm deletion diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index 27aba9e1..dff0d936 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -88,6 +88,10 @@ export const promptAction = async () => { name: 'Populate a collection', value: 'populate-collection', }, + { + name: 'Quit', + value: 'quit', + }, ], }); @@ -99,6 +103,9 @@ export const promptAction = async () => { case 'modify-hacker': await handleModifyHacker(); break; + case 'quit': + process.exit(0); + break; default: console.log('Invalid action'); } From 94218d75f734f74bafb38d82b25214ac2274b8f9 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Wed, 13 Sep 2023 23:50:19 -0500 Subject: [PATCH 08/15] add error handling --- scripts/dev-cli.ts | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index dff0d936..0a58fefa 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -1,7 +1,6 @@ -import { input, select } from '@inquirer/prompts'; +import { select } from '@inquirer/prompts'; import dbConnect from '../middleware/database'; import * as dotenv from 'dotenv'; -import application from '../models/application'; import { handleModifyHacker } from './cli-util/modify-hacker'; import { handleGetHacker } from './cli-util/get-hacker'; dotenv.config(); @@ -96,24 +95,29 @@ export const promptAction = async () => { }); // Perform action - switch (action) { - case 'get-hacker': - await handleGetHacker(); - break; - case 'modify-hacker': - await handleModifyHacker(); - break; - case 'quit': - process.exit(0); - break; - default: - console.log('Invalid action'); + try { + switch (action) { + case 'get-hacker': + await handleGetHacker(); + break; + case 'modify-hacker': + await handleModifyHacker(); + break; + case 'quit': + process.exit(0); + break; + default: + console.log('Invalid action'); + } + } catch (err) { + handleError(err as Error); } }; -// handle api error(a function that's called when API calls return 404) -const handleError = () => { - console.log('Error: You need to have the witness running'); +// handle error +const handleError = (err: Error) => { + console.log('An error has occurred! You are a dev, right? Fix it: '); + console.log(err); }; // Execute the CLI tool From 52652d9120b4d64129918b15e7bba625194c6c71 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Thu, 14 Sep 2023 00:05:18 -0500 Subject: [PATCH 09/15] finish implement join/leave team for hacker doc --- scripts/cli-util/modify-hacker.ts | 116 ++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 5 deletions(-) diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index d089e467..e801346c 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -1,8 +1,9 @@ import { input, select } from '@inquirer/prompts'; +import Application from '../../models/application'; +import Team from '../../models/team'; import User from '../../models/user'; import { promptAction } from '../dev-cli'; -import { ApplicationStatus, UserData } from '../../types/database'; -import Application from '../../models/application'; +import { ApplicationStatus, TeamData, UserData } from '../../types/database'; // TODO: zi /** @@ -60,10 +61,13 @@ export const handleModifyHacker = async () => { await deleteApplication(hacker); break; case 'join-team': + await joinTeam(hacker); break; case 'leave-team': + await leaveTeam(hacker); break; case 'nfc-check-in': + await nfcCheckIn(hacker); break; } }; @@ -156,11 +160,113 @@ const deleteApplication = async (hacker: UserData) => { return promptAction(); }; -const joinTeam = async () => {}; +const joinTeam = async (hacker: UserData) => { + const teamId = hacker.team; + + // check if hacker has a team + if (teamId) { + console.log('Hacker already has a team'); + return promptAction(); + } + + // get team invite code + const inviteCode = await input({ + message: 'Enter team invite code', + }); + + // query for team document + const team = await Team.findOne({ joinCode: inviteCode }); + + // check if team exists + if (!team) { + console.log('Team does not exist'); + return promptAction(); + } + + // confirm joining team + const confirm = await select({ + message: `Team Found! Are you sure you want to join it (${team._id})?`, + choices: [ + { + name: 'Yes', + value: true, + }, + { + name: 'No', + value: false, + }, + ], + }); + + // cancel if not confirmed + if (!confirm) { + console.log('Cancelled'); + return promptAction(); + } + + // perform joining team and log + await Team.updateOne({ _id: team._id }, { $push: { members: hacker._id } }); + await User.updateOne({ email: hacker.email }, { team: team._id }); + console.log('Joined team successfully'); +}; + +const leaveTeam = async (hacker: UserData) => { + const teamId = hacker.team; + + // check if hacker has a team + if (!teamId) { + console.log('Hacker does not have a team'); + return promptAction(); + } + + const teamDoc: TeamData | null = await Team.findById(teamId); + + // check if team exists + if (!teamDoc) { + console.log('Team does not exist. Clearing hacker team field'); + await User.updateOne({ email: hacker.email }, { team: null }); + return promptAction(); + } + + // confirm deletion + const confirm = await select({ + message: `Team Found! Are you sure you want to leave it (${teamDoc._id})?`, + choices: [ + { + name: 'Yes', + value: true, + }, + { + name: 'No', + value: false, + }, + ], + }); + + // cancel if not confirmed + if (!confirm) { + console.log('Cancelled'); + return promptAction(); + } + + // perform deletion and log + await Team.updateOne({ _id: teamId }, { $pull: { members: hacker._id } }); + await User.updateOne({ email: hacker.email }, { team: null }); + console.log('Left team successfully'); +}; + +const nfcCheckIn = async (hacker: UserData) => { + // get nfc id + const nfcId = await input({ + message: 'Enter nfc id', + }); -const leaveTeam = async () => {}; + // update hacker document and log + await User.updateOne({ email: hacker.email }, { nfcId, applicationStatus: ApplicationStatus.CHECKED_IN }); + console.log(`Updated hacker document with nfc id ${nfcId} and application status ${ApplicationStatus.CHECKED_IN}`); -const nfcCheckIn = async () => {}; + return promptAction(); +}; const getApplicationStatusString = (status: ApplicationStatus): string => { switch (status) { From 26fdf0946771f338a0871af6cc2b3591806b361a Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Thu, 14 Sep 2023 00:05:26 -0500 Subject: [PATCH 10/15] add better comments --- scripts/dev-cli.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index 0a58fefa..9b851a8d 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -7,6 +7,17 @@ dotenv.config(); /** * NOTE: To use this CLI tool, run `ts-node scripts/dev-cli.ts` in your terminal. + * + * executeCLI calls promptAction. + * + * promptAction calls one of the following functions: + * - handleGetHacker + * - handleGetTeam + * - handleModifyHacker + * - handleModifyTeam + * - handleClearCollection + * - handlePopulateCollection + * - process.exit(0) */ const executeCLI = async () => { // Select database From 152d3e72c51783a8a6fdacdfbf2a1882ade78b2e Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Thu, 14 Sep 2023 00:06:56 -0500 Subject: [PATCH 11/15] add TODO for nfc check in --- scripts/cli-util/modify-hacker.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/scripts/cli-util/modify-hacker.ts b/scripts/cli-util/modify-hacker.ts index e801346c..67e68312 100644 --- a/scripts/cli-util/modify-hacker.ts +++ b/scripts/cli-util/modify-hacker.ts @@ -255,17 +255,9 @@ const leaveTeam = async (hacker: UserData) => { console.log('Left team successfully'); }; +// TODO: this is not working const nfcCheckIn = async (hacker: UserData) => { - // get nfc id - const nfcId = await input({ - message: 'Enter nfc id', - }); - - // update hacker document and log - await User.updateOne({ email: hacker.email }, { nfcId, applicationStatus: ApplicationStatus.CHECKED_IN }); - console.log(`Updated hacker document with nfc id ${nfcId} and application status ${ApplicationStatus.CHECKED_IN}`); - - return promptAction(); + // TODO: zi }; const getApplicationStatusString = (status: ApplicationStatus): string => { From f9d80b787b09f4346d0a59186235fa3fa5312980 Mon Sep 17 00:00:00 2001 From: Gabriel Dong Date: Thu, 14 Sep 2023 17:46:15 -0500 Subject: [PATCH 12/15] feat: get-hacker cli --- scripts/cli-util/get-hacker.ts | 47 +++++++++++++++++++++++++++------- types/database.ts | 1 + 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/scripts/cli-util/get-hacker.ts b/scripts/cli-util/get-hacker.ts index a6c67c4d..c80c6f69 100644 --- a/scripts/cli-util/get-hacker.ts +++ b/scripts/cli-util/get-hacker.ts @@ -1,9 +1,10 @@ import { input, select } from '@inquirer/prompts'; import dbConnect from '../../middleware/database'; import User from '../../models/user'; +import Event from '../../models/event'; import team from '../../models/team'; import { promptAction } from '../dev-cli'; -import { UserData, TeamData } from '../../types/database'; +import { UserData, TeamData, EventData } from '../../types/database'; export const handleGetHacker = async () => { const hackerEmail = await input({ @@ -28,8 +29,8 @@ export const handleGetHacker = async () => { value: 'get-team', }, { - name: 'Get application', - value: 'get-application', + name: 'Get application status', + value: 'get-application-status', }, { name: 'Get document', @@ -43,30 +44,58 @@ export const handleGetHacker = async () => { switch (subAction1) { case 'get-events': - await getEvents(); + await getEvents(user); break; case 'get-team': await getTeam(user); break; - case 'get-application': - await getApplication(); + case 'get-application-status': + await getApplicationStatus(user); break; case 'get-document': - console.log(user); + await getDocument(user); break; default: console.log('Invalid action'); } }; -const getEvents = async () => {}; +const getEvents = async (user: UserData) => { + const events = user.eventsAttended; + const size = events.length; + + if (size === 0) console.log('No events attended yet! :('); + + for (const eventId of events) { + const event: EventData = JSON.parse(JSON.stringify(await Event.findOne({ _id: eventId }))); + console.log(event.name); + } + + console.log(''); + return promptAction(); +}; const getTeam = async (user: UserData) => { const teamId = user.team; const hackerTeam = JSON.parse(JSON.stringify(await team.findOne({ _id: teamId }))); + console.log('Team Document'); console.log(hackerTeam); + console.log(''); return promptAction(); }; -const getApplication = async () => {}; +const getApplicationStatus = async (user: UserData) => { + console.log(`Application status: ${user.applicationStatus}`); + + console.log(''); + return promptAction(); +}; + +const getDocument = async (user: UserData) => { + console.log('User Document:'); + console.log(user); + + console.log(''); + return promptAction(); +}; diff --git a/types/database.ts b/types/database.ts index 264549cf..72669c2a 100644 --- a/types/database.ts +++ b/types/database.ts @@ -46,6 +46,7 @@ export interface UserData { team?: mongoose.Schema.Types.ObjectId; application?: mongoose.Schema.Types.ObjectId; applicationStatus: ApplicationStatus; + eventsAttended: mongoose.Schema.Types.ObjectId[]; } export interface PreAddData { From d3a11d28f08d9fd7988071cd93ae900f0a0ed566 Mon Sep 17 00:00:00 2001 From: Gabriel Dong Date: Fri, 15 Sep 2023 03:53:19 -0500 Subject: [PATCH 13/15] feat: get teams --- scripts/cli-util/get-hacker.ts | 2 +- scripts/cli-util/get-team.ts | 82 ++++++++++++++++++++++++++++++++++ scripts/dev-cli.ts | 4 ++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 scripts/cli-util/get-team.ts diff --git a/scripts/cli-util/get-hacker.ts b/scripts/cli-util/get-hacker.ts index c80c6f69..52169936 100644 --- a/scripts/cli-util/get-hacker.ts +++ b/scripts/cli-util/get-hacker.ts @@ -4,7 +4,7 @@ import User from '../../models/user'; import Event from '../../models/event'; import team from '../../models/team'; import { promptAction } from '../dev-cli'; -import { UserData, TeamData, EventData } from '../../types/database'; +import { UserData, EventData } from '../../types/database'; export const handleGetHacker = async () => { const hackerEmail = await input({ diff --git a/scripts/cli-util/get-team.ts b/scripts/cli-util/get-team.ts new file mode 100644 index 00000000..f4a7a4c6 --- /dev/null +++ b/scripts/cli-util/get-team.ts @@ -0,0 +1,82 @@ +import { input, select } from '@inquirer/prompts'; +import dbConnect from '../../middleware/database'; +import User from '../../models/user'; +import Team from '../../models/team'; +import { promptAction } from '../dev-cli'; +import { UserData, TeamData } from '../../types/database'; + +export const handleGetTeam = async () => { + const teamName = await input({ + message: 'Enter team name', + }); + + const team: TeamData | null = JSON.parse(JSON.stringify(await Team.findOne({ name: teamName }))); + if (!team) { + console.log('team not found'); + return promptAction(); + } + + const subAction1 = await select({ + message: 'Select an action to perform', + choices: [ + { + name: 'Get schedule', + value: 'get-schedule', + }, + { + name: 'Get members', + value: 'get-members', + }, + { + name: 'Get document', + value: 'get-document', + }, + ], + }); + + // connect to db + await dbConnect(); + + switch (subAction1) { + case 'get-schedule': + await getSchedule(team); + break; + case 'get-members': + await getMembers(team); + break; + case 'get-document': + await getDocument(team); + break; + default: + console.log('Invalid action'); + } +}; + +const getSchedule = async (team: TeamData) => { + console.log('IN PROGRESS'); + console.log(''); + return promptAction(); +}; + +const getMembers = async (team: TeamData) => { + const memberIds = team.members; + + let count = 1; + for (const memberId of memberIds) { + const member: UserData = JSON.parse(JSON.stringify(await User.findOne({ _id: memberId }))); + console.log(`Member ${count++}:`); + console.log(`Name: ${member.name}`); + console.log(`Email: ${member.email}`); + } + + console.log(''); + return promptAction(); +}; + +const getDocument = async (team: TeamData) => { + console.log('Team Document:'); + console.log(team); + + console.log(''); + return promptAction(); +}; diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index 9b851a8d..5109e0d4 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -3,6 +3,7 @@ import dbConnect from '../middleware/database'; import * as dotenv from 'dotenv'; import { handleModifyHacker } from './cli-util/modify-hacker'; import { handleGetHacker } from './cli-util/get-hacker'; +import { handleGetTeam } from './cli-util/get-team'; dotenv.config(); /** @@ -111,6 +112,9 @@ export const promptAction = async () => { case 'get-hacker': await handleGetHacker(); break; + case 'get-team': + await handleGetTeam(); + break; case 'modify-hacker': await handleModifyHacker(); break; From 340d8b9066b841da1e9703ca49122d7c2e120762 Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Sat, 16 Sep 2023 15:27:43 -0500 Subject: [PATCH 14/15] =?UTF-8?q?add=20=F0=9F=8F=97=EF=B8=8F=20to=20denote?= =?UTF-8?q?=20in=20progress?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/dev-cli.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/dev-cli.ts b/scripts/dev-cli.ts index 5109e0d4..5e064016 100644 --- a/scripts/dev-cli.ts +++ b/scripts/dev-cli.ts @@ -74,7 +74,7 @@ export const promptAction = async () => { // 3. get entire JSON of their document }, { - name: "Modify a hacker's document", + name: "🏗️ Modify a hacker's document", value: 'modify-hacker', // sub-action: // 1. change application status @@ -83,7 +83,7 @@ export const promptAction = async () => { // 4. check in }, { - name: 'Modify a team', + name: '🏗️ Modify a team', value: 'modify-team', // sub-action: // 1. change team name @@ -92,11 +92,11 @@ export const promptAction = async () => { // 4. change devpost link? }, { - name: 'Clear a collection (dangerous)', + name: '🏗️ Clear a collection (dangerous)', value: 'clear-collection', }, { - name: 'Populate a collection', + name: '🏗️ Populate a collection', value: 'populate-collection', }, { From fa19c69f688e2ef3dd255a3114f6f1728c09d1fb Mon Sep 17 00:00:00 2001 From: Zi Nean Teoh Date: Sat, 16 Sep 2023 15:33:52 -0500 Subject: [PATCH 15/15] remove json parse and stringify bc redundant --- scripts/cli-util/get-hacker.ts | 25 +++++++++++++++++-------- scripts/cli-util/get-team.ts | 16 ++++++++++------ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/scripts/cli-util/get-hacker.ts b/scripts/cli-util/get-hacker.ts index 52169936..e474e152 100644 --- a/scripts/cli-util/get-hacker.ts +++ b/scripts/cli-util/get-hacker.ts @@ -2,16 +2,16 @@ import { input, select } from '@inquirer/prompts'; import dbConnect from '../../middleware/database'; import User from '../../models/user'; import Event from '../../models/event'; -import team from '../../models/team'; +import Team from '../../models/team'; import { promptAction } from '../dev-cli'; -import { UserData, EventData } from '../../types/database'; +import { UserData, EventData, TeamData } from '../../types/database'; export const handleGetHacker = async () => { const hackerEmail = await input({ message: 'Enter hacker email', }); - const user: UserData | null = JSON.parse(JSON.stringify(await User.findOne({ email: hackerEmail }))); + const user: UserData | null = await User.findOne({ email: hackerEmail }); if (!user) { console.log('Hacker not found'); return promptAction(); @@ -67,8 +67,13 @@ const getEvents = async (user: UserData) => { if (size === 0) console.log('No events attended yet! :('); for (const eventId of events) { - const event: EventData = JSON.parse(JSON.stringify(await Event.findOne({ _id: eventId }))); - console.log(event.name); + const event: EventData | null = await Event.findOne({ _id: eventId }); + if (!event) { + console.log('Event not found'); + return promptAction(); + } else { + console.log(`Event name: ${event.name}`); + } } console.log(''); @@ -77,9 +82,13 @@ const getEvents = async (user: UserData) => { const getTeam = async (user: UserData) => { const teamId = user.team; - const hackerTeam = JSON.parse(JSON.stringify(await team.findOne({ _id: teamId }))); - console.log('Team Document'); - console.log(hackerTeam); + const hackerTeam: TeamData | null = await Team.findOne({ _id: teamId }); + if (!hackerTeam) { + console.log('Team not found'); + return promptAction(); + } else { + console.log(`Team name: ${hackerTeam.name}`); + } console.log(''); return promptAction(); diff --git a/scripts/cli-util/get-team.ts b/scripts/cli-util/get-team.ts index f4a7a4c6..98a0a15e 100644 --- a/scripts/cli-util/get-team.ts +++ b/scripts/cli-util/get-team.ts @@ -10,7 +10,7 @@ export const handleGetTeam = async () => { message: 'Enter team name', }); - const team: TeamData | null = JSON.parse(JSON.stringify(await Team.findOne({ name: teamName }))); + const team: TeamData | null = await Team.findOne({ name: teamName }); if (!team) { console.log('team not found'); return promptAction(); @@ -63,13 +63,17 @@ const getMembers = async (team: TeamData) => { let count = 1; for (const memberId of memberIds) { - const member: UserData = JSON.parse(JSON.stringify(await User.findOne({ _id: memberId }))); - console.log(`Member ${count++}:`); - console.log(`Name: ${member.name}`); - console.log(`Email: ${member.email}`); + const member: UserData | null = await User.findOne({ _id: memberId }); + if (!member) { + console.log(`Member ${count++}:`); + console.log('Member not found'); + } else { + console.log(`Member ${count++}:`); + console.log(`Name: ${member.name}`); + console.log(`Email: ${member.email}`); + } } - console.log(''); return promptAction(); };