diff --git a/package-lock.json b/package-lock.json index 77cbddb..2a985d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "BSD-3-Clause", "dependencies": { "@jupyterhub/binderhub-client": "0.4.0", - "configurable-http-proxy": "^4.6.1", + "configurable-http-proxy": "^4.6.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-select": "^5.7.4", @@ -34,6 +34,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jest-fetch-mock": "^3.0.3", "react-test-renderer": "^18.3.1", "style-loader": "^3.3.2", "webpack": "^5.6.0", @@ -1868,16 +1869,18 @@ }, "node_modules/@colors/colors": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/@colors%2fcolors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "license": "MIT", "engines": { "node": ">=0.1.90" } }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "resolved": "http://verdaccio.ds.io:4873/@dabh%2fdiagnostics/-/diagnostics-2.0.3.tgz", "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "license": "MIT", "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -3658,8 +3661,9 @@ }, "node_modules/@types/triple-beam": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + "resolved": "http://verdaccio.ds.io:4873/@types%2ftriple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.5.10", @@ -4263,9 +4267,10 @@ } }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + "version": "3.2.6", + "resolved": "http://verdaccio.ds.io:4873/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", @@ -4572,8 +4577,9 @@ }, "node_modules/bintrees": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", - "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" + "resolved": "http://verdaccio.ds.io:4873/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", + "license": "MIT" }, "node_modules/body-parser": { "version": "1.20.2", @@ -4901,8 +4907,9 @@ }, "node_modules/color": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "license": "MIT", "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" @@ -4923,8 +4930,9 @@ }, "node_modules/color-string": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -4938,8 +4946,9 @@ }, "node_modules/colorspace": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "resolved": "http://verdaccio.ds.io:4873/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "license": "MIT", "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" @@ -5029,15 +5038,16 @@ "dev": true }, "node_modules/configurable-http-proxy": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/configurable-http-proxy/-/configurable-http-proxy-4.6.1.tgz", - "integrity": "sha512-l6AFE1Jiqlxiv+kIcwG3hrka3NDRorvsCyH9l6u8L7L30pzSO5Dhgq43RoS6vkXo7bolrdUIJWKw6tB8loDaFA==", + "version": "4.6.2", + "resolved": "http://verdaccio.ds.io:4873/configurable-http-proxy/-/configurable-http-proxy-4.6.2.tgz", + "integrity": "sha512-29kzKOyBlUmxBRq/ecKgsH712yLWUaBGESD3iq4UVKBL8NjyXGt+B3mv8xuq9gDn7PYVnotSbDMj5gScUJOF+w==", + "license": "BSD-3-Clause", "dependencies": { "commander": "~7.2", - "http-proxy": "^1.18.1", + "http-proxy-node16": "1.0.3", "prom-client": "14.2.0", "strftime": "~0.10.0", - "winston": "~3.11.0" + "winston": "~3.13.0" }, "bin": { "configurable-http-proxy": "bin/configurable-http-proxy" @@ -5222,6 +5232,16 @@ "node": ">=8" } }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "http://verdaccio.ds.io:4873/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -5677,8 +5697,9 @@ }, "node_modules/enabled": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + "resolved": "http://verdaccio.ds.io:4873/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -6528,8 +6549,9 @@ }, "node_modules/fecha": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + "resolved": "http://verdaccio.ds.io:4873/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "license": "MIT" }, "node_modules/file-entry-cache": { "version": "6.0.1", @@ -6657,8 +6679,9 @@ }, "node_modules/fn.name": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + "resolved": "http://verdaccio.ds.io:4873/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "license": "MIT" }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -7155,6 +7178,7 @@ "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -7202,6 +7226,20 @@ } } }, + "node_modules/http-proxy-node16": { + "version": "1.0.3", + "resolved": "http://verdaccio.ds.io:4873/http-proxy-node16/-/http-proxy-node16-1.0.3.tgz", + "integrity": "sha512-GReWWNIbJUCqYP7vcaaOGX0T+o8BpSP2VTZ4nCebJ9nbl3seUr5gCnLNpc4R2D0BK6kSY2hTsdpEV3QH2TobDg==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -8613,6 +8651,17 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-fetch-mock": { + "version": "3.0.3", + "resolved": "http://verdaccio.ds.io:4873/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", + "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-fetch": "^3.0.4", + "promise-polyfill": "^8.1.3" + } + }, "node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -9871,8 +9920,9 @@ }, "node_modules/kuler": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + "resolved": "http://verdaccio.ds.io:4873/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "license": "MIT" }, "node_modules/launch-editor": { "version": "2.6.1", @@ -9968,9 +10018,10 @@ "dev": true }, "node_modules/logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "version": "2.6.1", + "resolved": "http://verdaccio.ds.io:4873/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", + "license": "MIT", "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", @@ -10222,6 +10273,52 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "http://verdaccio.ds.io:4873/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "http://verdaccio.ds.io:4873/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "http://verdaccio.ds.io:4873/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "http://verdaccio.ds.io:4873/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -10418,8 +10515,9 @@ }, "node_modules/one-time": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "license": "MIT", "dependencies": { "fn.name": "1.x.x" } @@ -10902,8 +11000,9 @@ }, "node_modules/prom-client": { "version": "14.2.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/prom-client/-/prom-client-14.2.0.tgz", "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", + "license": "Apache-2.0", "dependencies": { "tdigest": "^0.1.1" }, @@ -10911,6 +11010,13 @@ "node": ">=10" } }, + "node_modules/promise-polyfill": { + "version": "8.3.0", + "resolved": "http://verdaccio.ds.io:4873/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", + "dev": true, + "license": "MIT" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -11514,9 +11620,10 @@ } }, "node_modules/safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "version": "2.5.0", + "resolved": "http://verdaccio.ds.io:4873/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", "engines": { "node": ">=10" } @@ -11846,16 +11953,18 @@ }, "node_modules/simple-swizzle": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "resolved": "http://verdaccio.ds.io:4873/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "license": "MIT", "dependencies": { "is-arrayish": "^0.3.1" } }, "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "resolved": "http://verdaccio.ds.io:4873/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" }, "node_modules/sisteransi": { "version": "1.0.5", @@ -11957,8 +12066,9 @@ }, "node_modules/stack-trace": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "resolved": "http://verdaccio.ds.io:4873/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "license": "MIT", "engines": { "node": "*" } @@ -11994,9 +12104,10 @@ } }, "node_modules/strftime": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.2.tgz", - "integrity": "sha512-Y6IZaTVM80chcMe7j65Gl/0nmlNdtt+KWPle5YeCAjmsBfw+id2qdaJ5MDrxUq+OmHKab+jHe7mUjU/aNMSZZg==", + "version": "0.10.3", + "resolved": "http://verdaccio.ds.io:4873/strftime/-/strftime-0.10.3.tgz", + "integrity": "sha512-DZrDUeIF73eKJ4/GgGuv8UHWcUQPYDYfDeQFj3jrx+JZl6GQE656MbHIpvbo4mEG9a5DgS8GRCc5DxJXD2udDQ==", + "license": "MIT", "engines": { "node": ">=0.2.0" } @@ -12241,8 +12352,9 @@ }, "node_modules/tdigest": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "resolved": "http://verdaccio.ds.io:4873/tdigest/-/tdigest-0.1.2.tgz", "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", + "license": "MIT", "dependencies": { "bintrees": "1.0.2" } @@ -12339,8 +12451,9 @@ }, "node_modules/text-hex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + "resolved": "http://verdaccio.ds.io:4873/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "license": "MIT" }, "node_modules/text-table": { "version": "0.2.0", @@ -12418,8 +12531,9 @@ }, "node_modules/triple-beam": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/triple-beam/-/triple-beam-1.4.1.tgz", "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "license": "MIT", "engines": { "node": ">= 14.0.0" } @@ -13303,33 +13417,35 @@ "dev": true }, "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.13.1", + "resolved": "http://verdaccio.ds.io:4873/winston/-/winston-3.13.1.tgz", + "integrity": "sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==", + "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.4.0", + "logform": "^2.6.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "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" } }, "node_modules/winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "version": "4.7.1", + "resolved": "http://verdaccio.ds.io:4873/winston-transport/-/winston-transport-4.7.1.tgz", + "integrity": "sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==", + "license": "MIT", "dependencies": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", + "logform": "^2.6.1", + "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" }, "engines": { @@ -14774,12 +14890,12 @@ }, "@colors/colors": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/@colors%2fcolors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==" }, "@dabh/diagnostics": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "resolved": "http://verdaccio.ds.io:4873/@dabh%2fdiagnostics/-/diagnostics-2.0.3.tgz", "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "requires": { "colorspace": "1.1.x", @@ -16213,7 +16329,7 @@ }, "@types/triple-beam": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "resolved": "http://verdaccio.ds.io:4873/@types%2ftriple-beam/-/triple-beam-1.3.5.tgz", "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, "@types/ws": { @@ -16708,9 +16824,9 @@ } }, "async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + "version": "3.2.6", + "resolved": "http://verdaccio.ds.io:4873/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" }, "asynckit": { "version": "0.4.0", @@ -16941,7 +17057,7 @@ }, "bintrees": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "resolved": "http://verdaccio.ds.io:4873/bintrees/-/bintrees-1.0.2.tgz", "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==" }, "body-parser": { @@ -17176,7 +17292,7 @@ }, "color": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "requires": { "color-convert": "^1.9.3", @@ -17198,7 +17314,7 @@ }, "color-string": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", @@ -17213,7 +17329,7 @@ }, "colorspace": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "resolved": "http://verdaccio.ds.io:4873/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "requires": { "color": "^3.1.3", @@ -17294,15 +17410,15 @@ "dev": true }, "configurable-http-proxy": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/configurable-http-proxy/-/configurable-http-proxy-4.6.1.tgz", - "integrity": "sha512-l6AFE1Jiqlxiv+kIcwG3hrka3NDRorvsCyH9l6u8L7L30pzSO5Dhgq43RoS6vkXo7bolrdUIJWKw6tB8loDaFA==", + "version": "4.6.2", + "resolved": "http://verdaccio.ds.io:4873/configurable-http-proxy/-/configurable-http-proxy-4.6.2.tgz", + "integrity": "sha512-29kzKOyBlUmxBRq/ecKgsH712yLWUaBGESD3iq4UVKBL8NjyXGt+B3mv8xuq9gDn7PYVnotSbDMj5gScUJOF+w==", "requires": { "commander": "~7.2", - "http-proxy": "^1.18.1", + "http-proxy-node16": "1.0.3", "prom-client": "14.2.0", "strftime": "~0.10.0", - "winston": "~3.11.0" + "winston": "~3.13.0" } }, "connect-history-api-fallback": { @@ -17437,6 +17553,15 @@ } } }, + "cross-fetch": { + "version": "3.1.8", + "resolved": "http://verdaccio.ds.io:4873/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dev": true, + "requires": { + "node-fetch": "^2.6.12" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -17761,7 +17886,7 @@ }, "enabled": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "encodeurl": { @@ -18401,7 +18526,7 @@ }, "fecha": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "resolved": "http://verdaccio.ds.io:4873/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "file-entry-cache": { @@ -18505,7 +18630,7 @@ }, "fn.name": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { @@ -18869,6 +18994,7 @@ "version": "1.18.1", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, "requires": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", @@ -18899,6 +19025,16 @@ "micromatch": "^4.0.2" } }, + "http-proxy-node16": { + "version": "1.0.3", + "resolved": "http://verdaccio.ds.io:4873/http-proxy-node16/-/http-proxy-node16-1.0.3.tgz", + "integrity": "sha512-GReWWNIbJUCqYP7vcaaOGX0T+o8BpSP2VTZ4nCebJ9nbl3seUr5gCnLNpc4R2D0BK6kSY2hTsdpEV3QH2TobDg==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -19880,6 +20016,16 @@ "jest-util": "^29.7.0" } }, + "jest-fetch-mock": { + "version": "3.0.3", + "resolved": "http://verdaccio.ds.io:4873/jest-fetch-mock/-/jest-fetch-mock-3.0.3.tgz", + "integrity": "sha512-Ux1nWprtLrdrH4XwE7O7InRY6psIi3GOsqNESJgMJ+M5cv4A8Lh7SN9d2V2kKRZ8ebAfcd1LNyZguAOb6JiDqw==", + "dev": true, + "requires": { + "cross-fetch": "^3.0.4", + "promise-polyfill": "^8.1.3" + } + }, "jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -20830,7 +20976,7 @@ }, "kuler": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" }, "launch-editor": { @@ -20909,9 +21055,9 @@ "dev": true }, "logform": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", - "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "version": "2.6.1", + "resolved": "http://verdaccio.ds.io:4873/logform/-/logform-2.6.1.tgz", + "integrity": "sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==", "requires": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", @@ -21097,6 +21243,39 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node-fetch": { + "version": "2.7.0", + "resolved": "http://verdaccio.ds.io:4873/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "http://verdaccio.ds.io:4873/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "http://verdaccio.ds.io:4873/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "http://verdaccio.ds.io:4873/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -21242,7 +21421,7 @@ }, "one-time": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "requires": { "fn.name": "1.x.x" @@ -21573,12 +21752,18 @@ }, "prom-client": { "version": "14.2.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-14.2.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/prom-client/-/prom-client-14.2.0.tgz", "integrity": "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA==", "requires": { "tdigest": "^0.1.1" } }, + "promise-polyfill": { + "version": "8.3.0", + "resolved": "http://verdaccio.ds.io:4873/promise-polyfill/-/promise-polyfill-8.3.0.tgz", + "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", + "dev": true + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -22008,9 +22193,9 @@ } }, "safe-stable-stringify": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", - "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" + "version": "2.5.0", + "resolved": "http://verdaccio.ds.io:4873/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==" }, "safer-buffer": { "version": "2.1.2", @@ -22285,15 +22470,15 @@ }, "simple-swizzle": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "resolved": "http://verdaccio.ds.io:4873/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { "is-arrayish": "^0.3.1" }, "dependencies": { "is-arrayish": { "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "resolved": "http://verdaccio.ds.io:4873/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" } } @@ -22385,8 +22570,8 @@ }, "stack-trace": { "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" + "resolved": "http://verdaccio.ds.io:4873/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "stack-utils": { "version": "2.0.6", @@ -22412,9 +22597,9 @@ "dev": true }, "strftime": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.2.tgz", - "integrity": "sha512-Y6IZaTVM80chcMe7j65Gl/0nmlNdtt+KWPle5YeCAjmsBfw+id2qdaJ5MDrxUq+OmHKab+jHe7mUjU/aNMSZZg==" + "version": "0.10.3", + "resolved": "http://verdaccio.ds.io:4873/strftime/-/strftime-0.10.3.tgz", + "integrity": "sha512-DZrDUeIF73eKJ4/GgGuv8UHWcUQPYDYfDeQFj3jrx+JZl6GQE656MbHIpvbo4mEG9a5DgS8GRCc5DxJXD2udDQ==" }, "string_decoder": { "version": "1.3.0", @@ -22584,7 +22769,7 @@ }, "tdigest": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", + "resolved": "http://verdaccio.ds.io:4873/tdigest/-/tdigest-0.1.2.tgz", "integrity": "sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==", "requires": { "bintrees": "1.0.2" @@ -22649,7 +22834,7 @@ }, "text-hex": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "resolved": "http://verdaccio.ds.io:4873/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, "text-table": { @@ -22713,7 +22898,7 @@ }, "triple-beam": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "resolved": "http://verdaccio.ds.io:4873/triple-beam/-/triple-beam-1.4.1.tgz", "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" }, "tslib": { @@ -23333,30 +23518,30 @@ "dev": true }, "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.13.1", + "resolved": "http://verdaccio.ds.io:4873/winston/-/winston-3.13.1.tgz", + "integrity": "sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==", "requires": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.4.0", + "logform": "^2.6.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "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" } }, "winston-transport": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", - "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "version": "4.7.1", + "resolved": "http://verdaccio.ds.io:4873/winston-transport/-/winston-transport-4.7.1.tgz", + "integrity": "sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==", "requires": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", + "logform": "^2.6.1", + "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, diff --git a/package.json b/package.json index f90c9de..dadd6ad 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@jupyterhub/binderhub-client": "0.4.0", - "configurable-http-proxy": "^4.6.1", + "configurable-http-proxy": "^4.6.2", "react": "^18.2.0", "react-dom": "^18.2.0", "react-select": "^5.7.4", @@ -48,6 +48,7 @@ "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jest-fetch-mock": "^3.0.3", "react-test-renderer": "^18.3.1", "style-loader": "^3.3.2", "webpack": "^5.6.0", @@ -55,6 +56,7 @@ "webpack-dev-server": "^4.9.3" }, "jest": { + "automock": false, "testEnvironment": "jsdom", "testMatch": [ "/src/**/*.test.js" diff --git a/setupTests.js b/setupTests.js index e20d173..980252d 100644 --- a/setupTests.js +++ b/setupTests.js @@ -1,4 +1,22 @@ +import { jest } from "@jest/globals"; import "@testing-library/jest-dom"; +import fetchMock from "jest-fetch-mock"; +fetchMock.enableMocks(); + +HTMLCanvasElement.prototype.getContext = () => {}; +Object.defineProperty(window, "matchMedia", { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); window.profileList = [ { diff --git a/src/ImageBuilder.jsx b/src/ImageBuilder.jsx index 74bead9..12a6159 100644 --- a/src/ImageBuilder.jsx +++ b/src/ImageBuilder.jsx @@ -1,4 +1,7 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; +import Select from "react-select"; +import useRepositoryField from "./hooks/useRepositoryField"; +import useRefField from "./hooks/useRefField"; async function buildImage(repo, ref, term, fitAddon, onImageBuilt) { const { BinderRepository } = await import("@jupyterhub/binderhub-client"); @@ -86,23 +89,33 @@ function ImageLogs({ setTerm, setFitAddon }) { ); } + export function ImageBuilder({ name }) { - const [repo, setRepo] = useState(""); + const { repo, repoId, repoFieldProps, repoError, repoIsValidating } = + useRepositoryField(); + const { ref, refError, refFieldProps, refIsLoading } = useRefField(repoId); + const repoFieldRef = useRef(); + const branchFieldRef = useRef(); + const [customImage, setCustomImage] = useState(""); - const [error, setError] = useState(""); - // FIXME: Allow users to actually configure this - const [ref, _] = useState("HEAD"); // eslint-disable-line no-unused-vars const [term, setTerm] = useState(null); const [fitAddon, setFitAddon] = useState(null); const handleBuildStart = async () => { if (!repo) { - setError("Provide a Github repository."); + repoFieldRef.current.focus(); + repoFieldRef.current.blur(); + return; + } + + if (!ref) { + branchFieldRef.current.focus(); + branchFieldRef.current.blur(); return; } - await buildImage(repo, ref, term, fitAddon, (imageName) => { + await buildImage(repoId, ref, term, fitAddon, (imageName) => { setCustomImage(imageName); term.write( "\nImage has been built! Click the start button to launch your server", @@ -116,28 +129,73 @@ export function ImageBuilder({ name }) { // don't generate the hidden input that posts the built image out. return ( <> -
+
+
+ Provider +
+
GitHub
+
+ +
- +
setRepo(e.target.value)} + ref={repoFieldRef} + {...repoFieldProps} + aria-invalid={!!repoError} /> - {error &&
{error}
} - + {repoIsValidating && ( +
+ Validating repository... +
+ )} + {repoError && ( +
{repoError}
+ )}
-
+ +
+
+ +
+
+ ); diff --git a/src/ImageBuilder.test.js b/src/ImageBuilder.test.js new file mode 100644 index 0000000..defc260 --- /dev/null +++ b/src/ImageBuilder.test.js @@ -0,0 +1,320 @@ +import { expect, test } from "@jest/globals"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; + +import ProfileForm from "./ProfileForm"; +import { SpawnerFormProvider } from "./state"; + +test("select repository by org/repo", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "org/repo"); + await user.click(document.body); + + const branchField = await screen.getByLabelText("Git Ref"); + await user.click(branchField); + await user.click(screen.getByText("main")); + expect(fetch.mock.calls[0][0]).toEqual( + "https://api.github.com/repos/org/repo", + ); +}); + +test("select repository by https://github.com/org/repo", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "https://github.com/org/repo"); + await user.click(document.body); + + const branchField = await screen.getByLabelText("Git Ref"); + await user.click(branchField); + await user.click(screen.getByText("main")); + expect(fetch.mock.calls[0][0]).toEqual( + "https://api.github.com/repos/org/repo", + ); +}); + +test("select repository by https://www.github.com/org/repo", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "https://www.github.com/org/repo"); + await user.click(document.body); + + const branchField = await screen.getByLabelText("Git Ref"); + await user.click(branchField); + await user.click(screen.getByText("main")); + expect(fetch.mock.calls[0][0]).toEqual( + "https://api.github.com/repos/org/repo", + ); +}); + +test("select repository by github.com/org/repo", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "github.com/org/repo"); + await user.click(document.body); + + const branchField = await screen.getByLabelText("Git Ref"); + await user.click(branchField); + await user.click(screen.getByText("main")); + expect(fetch.mock.calls[0][0]).toEqual( + "https://api.github.com/repos/org/repo", + ); +}); + +test("select repository by www.github.com/org/repo", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "www.github.com/org/repo"); + await user.click(document.body); + + const branchField = await screen.getByLabelText("Git Ref"); + await user.click(branchField); + await user.click(screen.getByText("main")); + expect(fetch.mock.calls[0][0]).toEqual( + "https://api.github.com/repos/org/repo", + ); +}); + +test("invalid org/repo string (not matching pattern)", async () => { + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "org"); + await user.click(document.body); + + expect( + screen.getByText( + "Provide the repository as the format 'organization/repository'.", + ), + ); + expect(screen.queryByLabelText("Git Ref")).toHaveAttribute("disabled"); +}); + +test("invalid org/repo string (wrong base URL)", async () => { + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "example.com/org/repo"); + await user.click(document.body); + + expect( + screen.getByText( + "Provide the repository as the format 'organization/repository'.", + ), + ); + expect(screen.queryByLabelText("Git Ref")).toHaveAttribute("disabled"); +}); + +test("repo not found", async () => { + fetch.mockResponseOnce("", { status: 400 }); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "https://github.com/org/repo"); + await user.click(document.body); + + expect(screen.queryByLabelText("Git Ref")).toHaveAttribute("disabled"); +}); + +test("no org/repo provided", async () => { + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + await user.click(screen.getByRole("button", { name: "Build image" })); + + expect( + screen.getByText( + "Provide the repository as the format 'organization/repository'.", + ), + ); +}); + +test("no branch selected", async () => { + fetch + .mockResponseOnce("") + .mockResponseOnce(JSON.stringify([{ name: "main" }, { name: "develop" }])) + .mockResponseOnce(JSON.stringify([{ name: "v1.0" }])); + const user = userEvent.setup(); + + render( + + + , + ); + const radio = screen.getByRole("radio", { + name: "CPU only No GPU, only CPU", + }); + await user.click(radio); + + const select = screen.getByLabelText("Image - dynamic image building"); + await user.click(select); + + await user.click(screen.getByText("Build your own image")); + + const repoField = screen.getByLabelText("Repository"); + await user.type(repoField, "org/repo"); + await user.click(document.body); + + expect(screen.queryByLabelText("Git Ref")).toBeInTheDocument(); + await user.click(screen.getByRole("button", { name: "Build image" })); + + expect(screen.getByText("Select a git ref.")); +}); diff --git a/src/form.css b/src/form.css index 4626d9f..3910bc8 100644 --- a/src/form.css +++ b/src/form.css @@ -75,6 +75,10 @@ border-radius: 4px; } +.profile-option-control-info { + margin-top: 0.5rem; +} + .profile-option-container.has-error label { color: red; } @@ -97,6 +101,11 @@ margin-top: 0.5rem; } +.right-button { + text-align: right; + margin-bottom: 2rem; +} + /* react-select styling */ .react-select-item-container.react-select-item-menu-display.react-select-item-selected .react-select-item-description { diff --git a/src/hooks/useRefField.js b/src/hooks/useRefField.js new file mode 100644 index 0000000..c872cb9 --- /dev/null +++ b/src/hooks/useRefField.js @@ -0,0 +1,64 @@ +import { useState, useEffect, useMemo } from "react"; + +function fetchRef(repository, refType) { + return fetch(`https://api.github.com/repos/${repository}/${refType}`).then( + (r) => { + if (r.ok) return r.json(); + }, + ); +} + +export default function useRefField(repository) { + const [value, setValue] = useState(""); + const [options, setOptions] = useState(); + const [error, setError] = useState(); + const [isLoading, setIsLoading] = useState(); + + const selectedOption = useMemo(() => { + if (!value || !options) return; + return options.find((option) => option.value === value); + }, [value]); + + useEffect(() => { + setIsLoading(true); + setOptions(); + if (repository) { + Promise.all([ + fetchRef(repository, "branches"), + fetchRef(repository, "tags"), + ]) + .then((results) => { + const refOptions = results.flat().map(({ name }) => ({ + label: name, + value: name, + })); + setOptions(refOptions); + }) + .finally(() => setIsLoading(false)); + } + }, [repository]); + + const onChange = (e) => { + setError(); + setValue(e.value); + }; + + const onBlur = () => { + setError(); + if (!value) { + setError("Select a git ref."); + } + }; + + return { + ref: value, + refError: error, + refIsLoading: isLoading, + refFieldProps: { + value: selectedOption, + options, + onChange, + onBlur, + }, + }; +} diff --git a/src/hooks/useRepositoryField.js b/src/hooks/useRepositoryField.js new file mode 100644 index 0000000..5363fd5 --- /dev/null +++ b/src/hooks/useRepositoryField.js @@ -0,0 +1,76 @@ +import { useCallback, useState } from "react"; + +function extractOrgAndRepo(value) { + let orgRepoString; + const orgRepoMatch = /^[^/]+\/[^/]+$/.exec(value); + + if (orgRepoMatch) { + orgRepoString = orgRepoMatch[0]; + } else { + const fullUrlMatch = + /^(?:https?:\/\/)?(?:www\.)?github\.com\/((?:[^/]+\/[^/]+|[^/]+\/[^/]+)?)\/?$/.exec( + value, + ); + if (fullUrlMatch) { + orgRepoString = fullUrlMatch[1]; + } + } + + return orgRepoString; +} + +export default function useRepositoryField() { + const [value, setValue] = useState(""); + const [error, setError] = useState(); + const [repoId, setRepoId] = useState(); + const [isValidating, setIsValidating] = useState(false); + + const validate = async () => { + setIsValidating(true); + setError(); + const orgRepoString = extractOrgAndRepo(value); + + if (!orgRepoString) { + return "Provide the repository as the format 'organization/repository'."; + } + + const repoExists = await fetch( + `https://api.github.com/repos/${orgRepoString}`, + { + method: "HEAD", + }, + ) + .then((r) => r.ok) + .finally(() => setIsValidating(false)); + + if (!repoExists) { + return "The repository doesn't exist or is not public."; + } + }; + + const onChange = useCallback((e) => { + setValue(e.target.value); + }, []); + + const onBlur = useCallback(async () => { + setRepoId(); + const err = await validate(); + if (err) { + setError(err); + } else { + setRepoId(extractOrgAndRepo(value)); + } + }, [value]); + + return { + repo: value, + repoError: error, + repoId, + repoIsValidating: isValidating, + repoFieldProps: { + value, + onChange, + onBlur, + }, + }; +}