diff --git a/NodeApp/package-lock.json b/NodeApp/package-lock.json index ba7bd845261fe22f359c5c422f92c34a7d1d9420..0db7390221eefed130a20b657379062cbd4abe64 100644 --- a/NodeApp/package-lock.json +++ b/NodeApp/package-lock.json @@ -9,6 +9,8 @@ "version": "3.6.0", "license": "AGPLv3", "dependencies": { + "@gitbeaker/core": "^39.34.3", + "@gitbeaker/requester-utils": "^39.34.3", "@gitbeaker/rest": "^39.34.3", "appdata-path": "^1.0.0", "axios": "^1.6.5", @@ -28,6 +30,7 @@ "semver": "^7.5.4", "tar-stream": "^3.1.6", "winston": "^3.11.0", + "winston-transport": "^4.7.0", "yaml": "^2.3.4", "zod": "^3.22.4", "zod-validation-error": "^3.0.0" @@ -253,9 +256,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "peer": true, "engines": { @@ -362,14 +365,14 @@ "peer": true }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -385,9 +388,9 @@ } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" @@ -400,9 +403,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -904,18 +907,18 @@ } }, "node_modules/@types/node": { - "version": "18.19.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.17.tgz", - "integrity": "sha512-SzyGKgwPzuWp2SHhlpXKzCX0pIOfcI4V2eF37nNBJOhwlegQ83omtVQ1XxZpDE06V/d6AQvfQdPfnw0tRC//Ng==", + "version": "18.19.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.24.tgz", + "integrity": "sha512-eghAz3gnbQbvnHqB+mgB2ZR3aH6RhdEmHGS48BnV75KceQPHqabkxKI0BbUSsqhqy2Ddhc2xD/VAR9ySZd57Lw==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, "node_modules/@types/semver": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.7.tgz", - "integrity": "sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==", + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", "dev": true }, "node_modules/@types/tar-stream": { @@ -1317,11 +1320,11 @@ } }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -1338,9 +1341,9 @@ "dev": true }, "node_modules/bare-events": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.0.tgz", - "integrity": "sha512-Yyyqff4PIFfSuthCZqLlPISTWHmnQxoPuAvkmgzsJEmG3CesdIv6Xweayl0JkCZJSB2yYIdJyEz97tpxNhgjbg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.1.tgz", + "integrity": "sha512-9GYPpsPFvrWBkelIhOhTWtkeZxVxZOdb3VnFTCzlOo3OjvmTvzLoZFUT8kNFACx0vJej6QPney1Cf9BvzCNE/A==", "optional": true }, "node_modules/base64-js": { @@ -1886,9 +1889,9 @@ } }, "node_modules/dotenv-vault": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/dotenv-vault/-/dotenv-vault-1.26.0.tgz", - "integrity": "sha512-2PNnlprtOdFEG9+hAAZxXegcjlJVZMSy88arnRR4YjwU/PwkDbdtk1uzw/D88D5EZ0b84n7YVQ6RccRXmW/Qzg==", + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/dotenv-vault/-/dotenv-vault-1.26.1.tgz", + "integrity": "sha512-v+RK6LXpJQWhaelTT2s0b5FQB0qziRBuGCrAgAeDHtgkDEA0NqF7OXYXsrnKTuCPnwBg0FmNJr4lZebCpJnrFA==", "dev": true, "dependencies": { "@oclif/core": "^1", @@ -1896,7 +1899,7 @@ "@oclif/plugin-not-found": "^2.3.34", "@oclif/plugin-update": "^3.1.16", "@oclif/plugin-warn-if-update-available": "^2.0.46", - "axios": "^0.27.2", + "axios": "^1.6.7", "chalk": "^4.1.2", "dotenv": "^16.3.1" }, @@ -1907,16 +1910,6 @@ "node": ">=16" } }, - "node_modules/dotenv-vault/node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" - } - }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -2009,17 +2002,17 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -2446,9 +2439,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "node_modules/follow-redirects": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", - "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -2786,9 +2779,9 @@ } }, "node_modules/hasown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", - "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dependencies": { "function-bind": "^1.1.2" }, @@ -3625,9 +3618,9 @@ } }, "node_modules/node-abi": { - "version": "3.55.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.55.0.tgz", - "integrity": "sha512-uPEjtyh2tFEvWYt4Jw7McOD5FPcHkcxm/tHZc5PWaDB3JYq0rGFUbgaAK+CT5pYpQddBfsZVWI08OwoRfdfbcQ==", + "version": "3.56.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.56.0.tgz", + "integrity": "sha512-fZjdhDOeRcaS+rcpve7XuwHBmktS1nS1gzgghwKUQQ8nTy2FdSDr6ZT8k6YhvlJeHmmQMYiT/IH9hfco5zeW2Q==", "dev": true, "dependencies": { "semver": "^7.3.5" @@ -4096,11 +4089,11 @@ } }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -4357,16 +4350,16 @@ } }, "node_modules/set-function-length": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", - "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.2", + "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.3", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4394,11 +4387,11 @@ } }, "node_modules/side-channel": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.5.tgz", - "integrity": "sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" @@ -4753,9 +4746,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", - "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, "engines": { "node": ">=16" @@ -4849,9 +4842,9 @@ } }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "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", @@ -4947,9 +4940,9 @@ } }, "node_modules/winston": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", - "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.12.0.tgz", + "integrity": "sha512-OwbxKaOlESDi01mC9rkM0dQqQt2I8DAUMRLZ/HpbwvDXm85IryEHgoogy5fziQy38PntgZsLlhAYHz//UPHZ5w==", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -4961,7 +4954,7 @@ "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" + "winston-transport": "^4.7.0" }, "engines": { "node": ">= 12.0.0" @@ -5028,9 +5021,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", - "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -5093,9 +5089,9 @@ } }, "node_modules/zod-validation-error": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.0.2.tgz", - "integrity": "sha512-21xGaDmnU7lJZ4J63n5GXWqi+rTzGy3gDHbuZ1jP6xrK/DEQGyOqs/xW7eH96tIfCOYm+ecCuT0bfajBRKEVUw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.0.3.tgz", + "integrity": "sha512-cETTrcMq3Ze58vhdR0zD37uJm/694I6mAxcf/ei5bl89cC++fBNxrC2z8lkFze/8hVMPwrbtrwXHR2LB50fpHw==", "engines": { "node": ">=18.0.0" }, diff --git a/NodeApp/package.json b/NodeApp/package.json index 87b5a5fcb2eda88e01efea2f3a8e4cdcd0b61c1b..e2000edb1bd959ddbca018e814fff620dda87e89 100644 --- a/NodeApp/package.json +++ b/NodeApp/package.json @@ -33,29 +33,31 @@ "test" : "echo \"Error: no test specified\" && exit 1" }, "dependencies" : { - "@gitbeaker/rest" : "^39.34.3", - "appdata-path" : "^1.0.0", - "axios" : "^1.6.5", - "boxen" : "^5.1.2", - "chalk" : "^4.1.2", - "commander" : "^11.1.0", - "dotenv" : "^16.3.1", - "dotenv-expand" : "^10.0.0", - "form-data" : "^4.0.0", - "fs-extra" : "^11.2.0", - "http-status-codes" : "^2.3.0", - "inquirer" : "^8.2.6", - "json5" : "^2.2.3", - "jsonwebtoken" : "^8.5.1", - "open" : "^8.4.2", - "ora" : "^5.4.1", - "semver" : "^7.5.4", - "tar-stream" : "^3.1.6", - "winston" : "^3.11.0", - "winston-transport" : "^4.7.0", - "yaml" : "^2.3.4", - "zod" : "^3.22.4", - "zod-validation-error": "^3.0.0" + "@gitbeaker/rest" : "^39.34.3", + "@gitbeaker/core" : "^39.34.3", + "@gitbeaker/requester-utils": "^39.34.3", + "appdata-path" : "^1.0.0", + "axios" : "^1.6.5", + "boxen" : "^5.1.2", + "chalk" : "^4.1.2", + "commander" : "^11.1.0", + "dotenv" : "^16.3.1", + "dotenv-expand" : "^10.0.0", + "form-data" : "^4.0.0", + "fs-extra" : "^11.2.0", + "http-status-codes" : "^2.3.0", + "inquirer" : "^8.2.6", + "json5" : "^2.2.3", + "jsonwebtoken" : "^8.5.1", + "open" : "^8.4.2", + "ora" : "^5.4.1", + "semver" : "^7.5.4", + "tar-stream" : "^3.1.6", + "winston" : "^3.11.0", + "winston-transport" : "^4.7.0", + "yaml" : "^2.3.4", + "zod" : "^3.22.4", + "zod-validation-error" : "^3.0.0" }, "devDependencies": { "@types/fs-extra" : "^11.0.4", diff --git a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts index d79934e18d201a61ac3f0f41465995395daf4d19..25d8f79a7362948eca623440336a3066d47a978e 100644 --- a/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts +++ b/NodeApp/src/commander/assignment/subcommands/AssignmentCreateCommand.ts @@ -9,9 +9,16 @@ import GlobalHelper from '../../../helpers/GlobalHelper'; import TextStyle from '../../../types/TextStyle'; +type CommandOptions = { name: string, template?: string, members_id?: Array<number>, members_username?: Array<string>, clone?: string | boolean } + + class AssignmentCreateCommand extends CommanderCommand { protected commandName: string = 'create'; + private members!: Array<Gitlab.UserSchema> | undefined; + private templateIdOrNamespace: string | null = null; + private assignment!: Assignment; + protected defineCommand() { this.command .description('create a new repository for an assignment') @@ -23,76 +30,71 @@ class AssignmentCreateCommand extends CommanderCommand { .action(this.commandAction.bind(this)); } - protected async commandAction(options: { name: string, template?: string, members_id?: Array<number>, members_username?: Array<string>, clone?: string | boolean }): Promise<void> { - let members!: Array<Gitlab.UserSchema> | false; - let templateIdOrNamespace: string | null = null; - let assignment!: Assignment; + private async dataRetrieval(options: CommandOptions) { + console.log(TextStyle.BLOCK('Please wait while we verify and retrieve data...')); - // Check access and retrieve data - { - console.log(TextStyle.BLOCK('Please wait while we verify and retrieve data...')); + if ( !await AccessesHelper.checkTeachingStaff() ) { + throw new Error(); + } - if ( !await AccessesHelper.checkTeachingStaff() ) { - return; - } + this.members = await GlobalHelper.gitlabManager.fetchMembers(options); + if ( !this.members ) { + throw new Error(); + } + + const assignmentGetSpinner: ora.Ora = ora('Checking assignment name availability').start(); + if ( await DojoBackendManager.getAssignment(options.name) ) { + assignmentGetSpinner.fail(`Assignment name "${ options.name }" is already taken. Please choose another one.`); + throw new Error(); + } + assignmentGetSpinner.succeed(`Assignment name "${ options.name }" is available`); - members = await GlobalHelper.gitlabManager.fetchMembers(options); - if ( !members ) { - return; + if ( options.template ) { + this.templateIdOrNamespace = options.template; + + if ( Number.isNaN(Number(this.templateIdOrNamespace)) ) { + this.templateIdOrNamespace = Toolbox.urlToPath(this.templateIdOrNamespace); } - const assignmentGetSpinner: ora.Ora = ora('Checking assignment name availability').start(); - if ( await DojoBackendManager.getAssignment(options.name) ) { - assignmentGetSpinner.fail(`Assignment name "${ options.name }" is already taken. Please choose another one.`); - return; + if ( !await DojoBackendManager.checkTemplateAccess(encodeURIComponent(this.templateIdOrNamespace)) ) { + throw new Error(); } - assignmentGetSpinner.succeed(`Assignment name "${ options.name }" is available`); + } + } - if ( options.template ) { - templateIdOrNamespace = options.template; + private async createAssignment(options: CommandOptions) { + console.log(TextStyle.BLOCK('Please wait while we are creating the assignment (approximately 10 seconds)...')); - if ( Number.isNaN(Number(templateIdOrNamespace)) ) { - templateIdOrNamespace = Toolbox.urlToPath(templateIdOrNamespace); - } + this.assignment = await DojoBackendManager.createAssignment(options.name, this.members!, this.templateIdOrNamespace); - if ( !await DojoBackendManager.checkTemplateAccess(encodeURIComponent(templateIdOrNamespace)) ) { - return; - } - } - } + const oraInfo = (message: string) => { + ora({ + text : message, + indent: 4 + }).start().info(); + }; - // Create the assignment - { - console.log(TextStyle.BLOCK('Please wait while we are creating the assignment (approximately 10 seconds)...')); - - try { - assignment = await DojoBackendManager.createAssignment(options.name, members, templateIdOrNamespace); - - const oraInfo = (message: string) => { - ora({ - text : message, - indent: 4 - }).start().info(); - }; - - oraInfo(`${ TextStyle.LIST_ITEM_NAME('Name:') } ${ assignment.name }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('Web URL:') } ${ assignment.gitlabCreationInfo.web_url }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('HTTP Repo:') } ${ assignment.gitlabCreationInfo.http_url_to_repo }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('SSH Repo:') } ${ assignment.gitlabCreationInfo.ssh_url_to_repo }`); - } catch ( error ) { - return; - } - } + oraInfo(`${ TextStyle.LIST_ITEM_NAME('Name:') } ${ this.assignment.name }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('Web URL:') } ${ this.assignment.gitlabCreationInfo.web_url }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('HTTP Repo:') } ${ this.assignment.gitlabCreationInfo.http_url_to_repo }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('SSH Repo:') } ${ this.assignment.gitlabCreationInfo.ssh_url_to_repo }`); + } - // Clone the repository - { - if ( options.clone ) { - console.log(TextStyle.BLOCK('Please wait while we are cloning the repository...')); + private async cloneRepository(options: CommandOptions) { + if ( options.clone ) { + console.log(TextStyle.BLOCK('Please wait while we are cloning the repository...')); - await GlobalHelper.gitlabManager.cloneRepository(options.clone, assignment.gitlabCreationInfo.ssh_url_to_repo, undefined, true, 0); - } + await GlobalHelper.gitlabManager.cloneRepository(options.clone, this.assignment.gitlabCreationInfo.ssh_url_to_repo, undefined, true, 0); } } + + protected async commandAction(options: CommandOptions): Promise<void> { + try { + await this.dataRetrieval(options); + await this.createAssignment(options); + await this.cloneRepository(options); + } catch ( e ) { /* Do nothing */ } + } } diff --git a/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts b/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts index 63567f1b982099a900885c1a7b0d82d547555d3b..335f44f9aef75f69b8e2f08fbc373a55902fa881 100644 --- a/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts +++ b/NodeApp/src/commander/exercise/subcommands/ExerciseCreateCommand.ts @@ -1,5 +1,4 @@ import CommanderCommand from '../../CommanderCommand'; -import chalk from 'chalk'; import ora from 'ora'; import DojoBackendManager from '../../../managers/DojoBackendManager'; import AccessesHelper from '../../../helpers/AccessesHelper'; @@ -10,9 +9,16 @@ import GlobalHelper from '../../../helpers/GlobalHelper'; import TextStyle from '../../../types/TextStyle'; +type CommandOptions = { assignment: string, members_id?: Array<number>, members_username?: Array<string>, clone?: string | boolean } + + class ExerciseCreateCommand extends CommanderCommand { protected commandName: string = 'create'; + private members!: Array<Gitlab.UserSchema> | undefined; + private assignment!: Assignment | undefined; + private exercise!: Exercise; + protected defineCommand() { this.command .description('create a new exercise from an assignment') @@ -23,80 +29,76 @@ class ExerciseCreateCommand extends CommanderCommand { .action(this.commandAction.bind(this)); } - protected async commandAction(options: { assignment: string, members_id?: Array<number>, members_username?: Array<string>, clone?: string | boolean }): Promise<void> { - let members!: Array<Gitlab.UserSchema> | false; - let assignment!: Assignment | undefined; - let exercise!: Exercise; - - // Check access and retrieve data - { - console.log(TextStyle.BLOCK('Please wait while we verify and retrieve data...')); - - if ( !await AccessesHelper.checkStudent() ) { - return; - } - - members = await GlobalHelper.gitlabManager.fetchMembers(options); - if ( !members ) { - return; - } - - ora('Checking assignment:').start().info(); - const assignmentGetSpinner: ora.Ora = ora({ - text : 'Checking if assignment exists', - indent: 4 - }).start(); - assignment = await DojoBackendManager.getAssignment(options.assignment); - if ( !assignment ) { - assignmentGetSpinner.fail(`Assignment "${ options.assignment }" doesn't exists`); - return; - } - assignmentGetSpinner.succeed(`Assignment "${ options.assignment }" exists`); - - const assignmentPublishedSpinner: ora.Ora = ora({ - text : 'Checking if assignment is published', - indent: 4 - }).start(); - if ( !assignment.published ) { - assignmentPublishedSpinner.fail(`Assignment "${ assignment.name }" isn't published`); - return; - } - assignmentPublishedSpinner.succeed(`Assignment "${ assignment.name }" is published`); + private async dataRetrieval(options: CommandOptions) { + console.log(TextStyle.BLOCK('Please wait while we verify and retrieve data...')); + + if ( !await AccessesHelper.checkStudent() ) { + throw new Error(); } - //Create the exercise - { - console.log(TextStyle.BLOCK('Please wait while we are creating the exercise (approximately 10 seconds)...')); - - try { - exercise = await DojoBackendManager.createExercise(assignment.name, members); - - const oraInfo = (message: string) => { - ora({ - text : message, - indent: 4 - }).start().info(); - }; - - oraInfo(`${ TextStyle.LIST_ITEM_NAME('Id:') } ${ exercise.id }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('Name:') } ${ exercise.name }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('Web URL:') } ${ exercise.gitlabCreationInfo.web_url }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('HTTP Repo:') } ${ exercise.gitlabCreationInfo.http_url_to_repo }`); - oraInfo(`${ TextStyle.LIST_ITEM_NAME('SSH Repo:') } ${ exercise.gitlabCreationInfo.ssh_url_to_repo }`); - } catch ( error ) { - return; - } + this.members = await GlobalHelper.gitlabManager.fetchMembers(options); + if ( !this.members ) { + throw new Error(); } - // Clone the repository - { - if ( options.clone ) { - console.log(TextStyle.BLOCK('Please wait while we are cloning the repository...')); + ora('Checking assignment:').start().info(); + const assignmentGetSpinner: ora.Ora = ora({ + text : 'Checking if assignment exists', + indent: 4 + }).start(); + this.assignment = await DojoBackendManager.getAssignment(options.assignment); + if ( !this.assignment ) { + assignmentGetSpinner.fail(`Assignment "${ options.assignment }" doesn't exists`); + throw new Error(); + } + assignmentGetSpinner.succeed(`Assignment "${ options.assignment }" exists`); + + const assignmentPublishedSpinner: ora.Ora = ora({ + text : 'Checking if assignment is published', + indent: 4 + }).start(); + if ( !this.assignment.published ) { + assignmentPublishedSpinner.fail(`Assignment "${ this.assignment.name }" isn't published`); + throw new Error(); + } + assignmentPublishedSpinner.succeed(`Assignment "${ this.assignment.name }" is published`); + } + + private async createExercise() { + console.log(TextStyle.BLOCK('Please wait while we are creating the exercise (approximately 10 seconds)...')); - await GlobalHelper.gitlabManager.cloneRepository(options.clone, exercise.gitlabCreationInfo.ssh_url_to_repo, `DojoExercise - ${ exercise.assignmentName }`, true, 0); - } + this.exercise = await DojoBackendManager.createExercise(this.assignment!.name, this.members!); + + const oraInfo = (message: string) => { + ora({ + text : message, + indent: 4 + }).start().info(); + }; + + oraInfo(`${ TextStyle.LIST_ITEM_NAME('Id:') } ${ this.exercise.id }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('Name:') } ${ this.exercise.name }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('Web URL:') } ${ this.exercise.gitlabCreationInfo.web_url }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('HTTP Repo:') } ${ this.exercise.gitlabCreationInfo.http_url_to_repo }`); + oraInfo(`${ TextStyle.LIST_ITEM_NAME('SSH Repo:') } ${ this.exercise.gitlabCreationInfo.ssh_url_to_repo }`); + } + + private async cloneRepository(options: CommandOptions) { + if ( options.clone ) { + console.log(TextStyle.BLOCK('Please wait while we are cloning the repository...')); + + await GlobalHelper.gitlabManager.cloneRepository(options.clone, this.exercise.gitlabCreationInfo.ssh_url_to_repo, `DojoExercise - ${ this.exercise.assignmentName }`, true, 0); } } + + + protected async commandAction(options: CommandOptions): Promise<void> { + try { + await this.dataRetrieval(options); + await this.createExercise(); + await this.cloneRepository(options); + } catch ( e ) { /* Do nothing */ } + } } diff --git a/NodeApp/src/helpers/AutoCompletionHelper.ts b/NodeApp/src/helpers/AutoCompletionHelper.ts index f2d3cbd6ff66df11f1885a0b17419919728c11db..13760c3927e123a13fc5ddb4c15048cee82944a7 100644 --- a/NodeApp/src/helpers/AutoCompletionHelper.ts +++ b/NodeApp/src/helpers/AutoCompletionHelper.ts @@ -67,8 +67,6 @@ complete -f -c dojo function isHidden(cmd: Command): boolean { return (cmd as Command & { _hidden: boolean })._hidden; - const isDone: boolean = false; - } function isLeaf(cmd: Command): boolean { diff --git a/NodeApp/src/managers/DojoBackendManager.ts b/NodeApp/src/managers/DojoBackendManager.ts index f536d183cc393ca41062016d56cec18ccd7faa0d..f287fc99760f35acdc7d04c1c132f3f944ea0f87 100644 --- a/NodeApp/src/managers/DojoBackendManager.ts +++ b/NodeApp/src/managers/DojoBackendManager.ts @@ -1,7 +1,6 @@ import axios, { AxiosError } from 'axios'; import ora from 'ora'; import ApiRoute from '../sharedByClients/types/Dojo/ApiRoute'; -import { StatusCodes } from 'http-status-codes'; import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; import Assignment from '../sharedByClients/models/Assignment'; import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; @@ -31,7 +30,7 @@ class DojoBackendManager { spinner.fail(`Assignment creation error: An unknown error occurred while creating the assignment on Gitlab. Please try again later or contact an administrator.`); break; case DojoStatusCode.MAX_EXERCISE_PER_ASSIGNMENT_REACHED: - spinner.fail(`The following users have reached the maximum number of exercise of this assignment : ${ ((error.response.data as DojoBackendResponse<Array<GitlabUser>>).data).map(user => user.name).join(', ') }.`); + spinner.fail(`The following users have reached the maximum number of exercise of this assignment : ${ ((error.response.data as DojoBackendResponse<Array<Gitlab.UserSchema>>).data).map(user => user.name).join(', ') }.`); break; case DojoStatusCode.EXERCISE_CREATION_GITLAB_ERROR: spinner.fail(`Exercise creation error: An unknown error occurred while creating the exercise on Gitlab. Please try again later or contact an administrator.`); diff --git a/NodeApp/src/managers/GitlabManager.ts b/NodeApp/src/managers/GitlabManager.ts index dda8d3991753affb473ae8f627d4b975c9d84fe4..91763e0551cea7b2e27ee6af382d6465956c0f7c 100644 --- a/NodeApp/src/managers/GitlabManager.ts +++ b/NodeApp/src/managers/GitlabManager.ts @@ -1,14 +1,12 @@ -import ora from 'ora'; -import SharedConfig from '../shared/config/SharedConfig'; -import fs from 'fs-extra'; -import { spawn } from 'child_process'; -import { Gitlab, UserSchema } from '@gitbeaker/rest'; -import * as GitlabCore from '@gitbeaker/core'; -import { EditNotificationSettingsOptions } from '@gitbeaker/core'; -import { GitbeakerRequestError } from '@gitbeaker/requester-utils'; -import { StatusCodes } from 'http-status-codes'; -import { NotificationSettingSchema } from '@gitbeaker/core/dist'; -import GlobalHelper from '../helpers/GlobalHelper'; +import ora from 'ora'; +import SharedConfig from '../shared/config/SharedConfig'; +import fs from 'fs-extra'; +import { spawn } from 'child_process'; +import { Gitlab, NotificationSettingSchema, UserSchema } from '@gitbeaker/rest'; +import * as GitlabCore from '@gitbeaker/core'; +import { GitbeakerRequestError } from '@gitbeaker/requester-utils'; +import { StatusCodes } from 'http-status-codes'; +import GlobalHelper from '../helpers/GlobalHelper'; type getGitlabUser = (param: number | string) => Promise<UserSchema | undefined> @@ -118,7 +116,7 @@ class GitlabManager { return this.executeGitlabRequest(() => this.api.NotificationSettings.show()); } - public setNotificationSettings(newSettings: EditNotificationSettingsOptions) { + public setNotificationSettings(newSettings: GitlabCore.EditNotificationSettingsOptions) { return this.executeGitlabRequest(() => this.api.NotificationSettings.edit(newSettings)); } @@ -154,25 +152,25 @@ class GitlabManager { } public async getUsersById(ids: Array<number>, verbose: boolean = false, verboseIndent: number = 0): Promise<Array<UserSchema | undefined>> { - return await this.getGitlabUsers(ids, GlobalHelper.sharedGitlabManager.getUserById.bind(GlobalHelper.sharedGitlabManager) as getGitlabUser, verbose, verboseIndent); + return this.getGitlabUsers(ids, GlobalHelper.sharedGitlabManager.getUserById.bind(GlobalHelper.sharedGitlabManager) as getGitlabUser, verbose, verboseIndent); } public async getUsersByUsername(usernames: Array<string>, verbose: boolean = false, verboseIndent: number = 0): Promise<Array<UserSchema | undefined>> { - return await this.getGitlabUsers(usernames, GlobalHelper.sharedGitlabManager.getUserByUsername.bind(GlobalHelper.sharedGitlabManager) as getGitlabUser, verbose, verboseIndent); + return this.getGitlabUsers(usernames, GlobalHelper.sharedGitlabManager.getUserByUsername.bind(GlobalHelper.sharedGitlabManager) as getGitlabUser, verbose, verboseIndent); } - public async fetchMembers(options: { members_id?: Array<number>, members_username?: Array<string> }): Promise<Array<UserSchema> | false> { + public async fetchMembers(options: { members_id?: Array<number>, members_username?: Array<string> }): Promise<Array<UserSchema> | undefined> { if ( options.members_id || options.members_username ) { ora('Checking Gitlab members:').start().info(); } let members: Array<UserSchema> = []; - async function getMembers<T>(context: unknown, functionName: string, paramsToSearch: Array<T>): Promise<boolean> { - const result = await ((context as { [functionName: string]: (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<UserSchema | undefined>> })[functionName])(paramsToSearch, true, 8); + async function isUsersExists<T>(context: unknown, functionName: string, paramsToSearch: Array<T>): Promise<boolean> { + const users = await ((context as { [functionName: string]: (arg: Array<T>, verbose: boolean, verboseIndent: number) => Promise<Array<UserSchema | undefined>> })[functionName])(paramsToSearch, true, 8); - if ( result.every(user => user) ) { - members = members.concat(result as Array<UserSchema>); + if ( users.every(user => user) ) { + members = members.concat(users as Array<UserSchema>); return true; } else { return false; @@ -187,7 +185,7 @@ class GitlabManager { indent: 4 }).start().info(); - result = await getMembers(this, 'getUsersById', options.members_id); + result = await isUsersExists(this, 'getUsersById', options.members_id); } if ( options.members_username ) { @@ -196,16 +194,10 @@ class GitlabManager { indent: 4 }).start().info(); - result = result && await getMembers(this, 'getUsersByUsername', options.members_username); + result = result && await isUsersExists(this, 'getUsersByUsername', options.members_username); } - if ( !result ) { - return false; - } - - members = members.removeObjectDuplicates(gitlabUser => gitlabUser.id); - - return members; + return result ? members.removeObjectDuplicates(gitlabUser => gitlabUser.id) : undefined; } public async cloneRepository(clonePath: string | boolean, repositorySshUrl: string, folderName?: string, verbose: boolean = false, verboseIndent: number = 0) { diff --git a/NodeApp/src/managers/HttpManager.ts b/NodeApp/src/managers/HttpManager.ts index 1dfae2351c456b8beb79a465866a3b9a49fc8ccb..ba4b22af6f7a4657cb15174379b31990bbedde9f 100644 --- a/NodeApp/src/managers/HttpManager.ts +++ b/NodeApp/src/managers/HttpManager.ts @@ -1,16 +1,14 @@ -import axios, { AxiosError, AxiosRequestConfig, AxiosRequestHeaders } from 'axios'; -import SessionManager from './SessionManager'; -import FormData from 'form-data'; -import { StatusCodes } from 'http-status-codes'; -import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; -import { version } from '../config/Version'; -import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; -import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; -import boxen from 'boxen'; -import Config from '../config/Config'; -import { stateConfigFile } from '../config/ConfigFiles'; -import SharedConfig from '../shared/config/SharedConfig'; -import TextStyle from '../types/TextStyle'; +import axios, { AxiosError, AxiosRequestHeaders } from 'axios'; +import SessionManager from './SessionManager'; +import FormData from 'form-data'; +import { StatusCodes } from 'http-status-codes'; +import ClientsSharedConfig from '../sharedByClients/config/ClientsSharedConfig'; +import { version } from '../config/Version'; +import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; +import DojoStatusCode from '../shared/types/Dojo/DojoStatusCode'; +import boxen from 'boxen'; +import { stateConfigFile } from '../config/ConfigFiles'; +import TextStyle from '../types/TextStyle'; class HttpManager { diff --git a/NodeApp/src/managers/SessionManager.ts b/NodeApp/src/managers/SessionManager.ts index aa48e1099e9160c5e475d843c076d50acadef611..db7f4ee7e242bf36ba4cca38be530fb16796ceb9 100644 --- a/NodeApp/src/managers/SessionManager.ts +++ b/NodeApp/src/managers/SessionManager.ts @@ -220,7 +220,7 @@ class SessionManager { throw error; } - const isGitlabTokensValid = (await GlobalHelper.gitlabManager.testToken()).every((value) => value); + const isGitlabTokensValid = (await GlobalHelper.gitlabManager.testToken()).every(value => value); if ( !isGitlabTokensValid ) { throw new Error('Gitlab tokens are invalid'); }