diff --git a/package-lock.json b/package-lock.json index fe813d4..180fea4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,19 @@ "@mui/lab": "^9.0.0-beta.2", "@mui/material": "^9.0.0", "@reduxjs/toolkit": "^2.11.2", + "cla-wrapper": "^0.3.10", + "compression": "^1.7.4", + "cors": "^2.8.5", "diff": "^8.0.3", "dompurify": "^3.2.7", "electron-debug": "^3.2.0", "electron-log": "^4.4.8", "electron-updater": "^6.1.9", + "express": "^4.17.1", + "express-rate-limit": "^5.2.6", + "jszip": "^3.2.2", "parse-define-xml": "^0.1.7", + "query-string": "^6.8.3", "react": "^19.2.7", "react-dom": "^19.2.7", "react-redux": "^9.3.0", @@ -6035,7 +6042,6 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, "license": "MIT", "dependencies": { "mime-types": "~2.1.34", @@ -6049,7 +6055,6 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -6166,7 +6171,6 @@ "version": "6.14.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -6678,7 +6682,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true, "license": "MIT" }, "node_modules/array-includes": { @@ -6834,13 +6837,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=0.8" } @@ -6904,7 +6914,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/at-least-node": { @@ -6933,6 +6942,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "license": "MIT" + }, "node_modules/axe-core": { "version": "4.11.3", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.3.tgz", @@ -7210,6 +7234,15 @@ "dev": true, "license": "MIT" }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -7249,7 +7282,6 @@ "version": "1.20.5", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -7274,7 +7306,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -7284,7 +7315,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -7297,7 +7327,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/bonjour-service": { @@ -7491,7 +7520,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -7652,7 +7680,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -7666,7 +7693,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -7746,6 +7772,12 @@ ], "license": "CC-BY-4.0" }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "license": "Apache-2.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -7861,6 +7893,19 @@ "dev": true, "license": "MIT" }, + "node_modules/cla-wrapper": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/cla-wrapper/-/cla-wrapper-0.3.10.tgz", + "integrity": "sha512-nBmFEdntT5ThSdRYPjV1guY+XCGPRh+yGcCSXxraRVWlBXqzcTK21EYu5tWBOFiEUYzviTeAfdRGdVXhJNIJRA==", + "license": "MIT", + "dependencies": { + "fast-xml-parser": "^3.19.0", + "json2csv": "^5.0.0", + "qs": "^6.9.4", + "request": "^2.88.2", + "types": "^0.1.1" + } + }, "node_modules/clean-css": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", @@ -8056,7 +8101,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -8089,7 +8133,6 @@ "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": ">= 1.43.0 < 2" @@ -8102,7 +8145,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -8121,7 +8163,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -8131,7 +8172,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/concat-map": { @@ -8206,7 +8246,6 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -8219,7 +8258,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -8235,7 +8273,6 @@ "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -8245,7 +8282,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true, "license": "MIT" }, "node_modules/core-js": { @@ -8290,9 +8326,25 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, "license": "MIT" }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -8716,6 +8768,18 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-urls": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", @@ -8833,6 +8897,15 @@ "dev": true, "license": "MIT" }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -8980,7 +9053,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -8990,7 +9062,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -9010,7 +9081,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8", @@ -9363,7 +9433,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -9388,11 +9457,20 @@ "dev": true, "license": "MIT" }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true, "license": "MIT" }, "node_modules/ejs": { @@ -9706,7 +9784,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -9892,7 +9969,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -9946,7 +10022,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -10024,7 +10099,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true, "license": "MIT" }, "node_modules/escape-string-regexp": { @@ -11143,7 +11217,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11240,7 +11313,6 @@ "version": "4.22.2", "resolved": "https://registry.npmjs.org/express/-/express-4.22.2.tgz", "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", - "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -11283,11 +11355,16 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", + "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==", + "license": "MIT" + }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -11297,7 +11374,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, + "license": "MIT" + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, "node_modules/extsprintf": { @@ -11315,7 +11397,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-diff": { @@ -11359,7 +11440,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -11386,6 +11466,22 @@ ], "license": "BSD-3-Clause" }, + "node_modules/fast-xml-parser": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "license": "MIT", + "dependencies": { + "strnum": "^1.0.4" + }, + "bin": { + "xml2js": "cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", @@ -11518,11 +11614,19 @@ "node": ">=8" } }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/finalhandler": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -11541,7 +11645,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -11551,7 +11654,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/find-root": { @@ -11739,6 +11841,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", @@ -11760,7 +11871,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11770,7 +11880,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -11906,7 +12015,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -11941,7 +12049,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -11998,6 +12105,15 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -12129,7 +12245,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -12232,6 +12347,29 @@ "node": ">=0.10.0" } }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/harmony-reflect": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", @@ -12305,7 +12443,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -12603,7 +12740,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, "license": "MIT", "dependencies": { "depd": "~2.0.0", @@ -12681,6 +12817,21 @@ } } }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -12821,7 +12972,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "dev": true, "license": "MIT" }, "node_modules/immer": { @@ -12936,7 +13086,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/internal-slot": { @@ -13467,6 +13616,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -13576,6 +13731,12 @@ "node": ">=0.10.0" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "license": "MIT" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -14795,6 +14956,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, "node_modules/jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", @@ -14908,11 +15075,16 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -14926,9 +15098,35 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC", - "optional": true + "license": "ISC" + }, + "node_modules/json2csv": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.7.tgz", + "integrity": "sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "commander": "^6.1.0", + "jsonparse": "^1.3.1", + "lodash.get": "^4.4.2" + }, + "bin": { + "json2csv": "bin/json2csv.js" + }, + "engines": { + "node": ">= 10", + "npm": ">= 6.13.0" + } + }, + "node_modules/json2csv/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } }, "node_modules/json5": { "version": "2.2.3", @@ -14955,6 +15153,53 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -14975,7 +15220,6 @@ "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dev": true, "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", @@ -14988,14 +15232,12 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, "license": "MIT" }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -15011,14 +15253,12 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, "license": "MIT" }, "node_modules/jszip/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -15131,7 +15371,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dev": true, "license": "MIT", "dependencies": { "immediate": "~3.0.5" @@ -15228,6 +15467,13 @@ "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", "license": "MIT" }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -15457,7 +15703,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -15474,7 +15719,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -15504,7 +15748,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -15531,7 +15774,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -15568,7 +15810,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -15578,7 +15819,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -15871,7 +16111,6 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -16409,6 +16648,15 @@ "dev": true, "license": "MIT" }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -16422,7 +16670,6 @@ "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -16542,7 +16789,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -16555,7 +16801,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -16778,7 +17023,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, "license": "(MIT AND Zlib)" }, "node_modules/param-case": { @@ -16861,7 +17105,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -16952,7 +17195,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", - "dev": true, "license": "MIT" }, "node_modules/path-type": { @@ -16979,6 +17221,12 @@ "url": "https://github.com/sponsors/jet2jet" } }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -17819,7 +18067,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, "license": "MIT" }, "node_modules/progress": { @@ -17900,7 +18147,6 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -17914,7 +18160,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" @@ -17924,7 +18169,6 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -17948,7 +18192,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -17975,7 +18218,6 @@ "version": "6.15.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -17987,6 +18229,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -18042,7 +18302,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -18052,7 +18311,6 @@ "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -18068,7 +18326,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -18383,6 +18640,84 @@ "strip-ansi": "^6.0.1" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", + "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18713,7 +19048,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -18769,7 +19103,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, "license": "MIT" }, "node_modules/sanitize-filename": { @@ -18912,7 +19245,6 @@ "version": "0.19.2", "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dev": true, "license": "MIT", "dependencies": { "debug": "2.6.9", @@ -18937,7 +19269,6 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -18947,14 +19278,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, "license": "MIT" }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, "license": "MIT", "bin": { "mime": "cli.js" @@ -19085,7 +19414,6 @@ "version": "1.16.3", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dev": true, "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", @@ -19150,14 +19478,12 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true, "license": "ISC" }, "node_modules/shallow-clone": { @@ -19213,7 +19539,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -19233,7 +19558,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -19250,7 +19574,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -19269,7 +19592,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -19508,6 +19830,15 @@ "wbuf": "^1.7.3" } }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -19516,6 +19847,31 @@ "license": "BSD-3-Clause", "optional": true }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ssri": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", @@ -19580,7 +19936,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -19600,6 +19955,15 @@ "node": ">= 0.4" } }, + "node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -19855,6 +20219,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, "node_modules/style-loader": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", @@ -20500,7 +20876,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.6" @@ -20874,6 +21249,24 @@ "dev": true, "license": "0BSD" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -20914,7 +21307,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -21002,6 +21394,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/types": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/types/-/types-0.1.1.tgz", + "integrity": "sha512-JuntZtJj4MKLE9x/XBs7IjsznYhzETwr34pw3XJTKvgYtAMdeMG+o8x8U85E5Lm6eCPa1DdOdGVsHMwq4ZnZAg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -21176,7 +21577,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" @@ -21277,7 +21677,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -21361,7 +21760,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/utila": { @@ -21375,7 +21773,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4.0" @@ -21424,7 +21821,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" diff --git a/package.json b/package.json index 8be7c26..e4627df 100644 --- a/package.json +++ b/package.json @@ -107,12 +107,19 @@ "@mui/lab": "^9.0.0-beta.2", "@mui/material": "^9.0.0", "@reduxjs/toolkit": "^2.11.2", + "cla-wrapper": "^0.3.10", + "compression": "^1.7.4", + "cors": "^2.8.5", "diff": "^8.0.3", "dompurify": "^3.2.7", "electron-debug": "^3.2.0", "electron-log": "^4.4.8", "electron-updater": "^6.1.9", + "express": "^4.17.1", + "express-rate-limit": "^5.2.6", + "jszip": "^3.2.2", "parse-define-xml": "^0.1.7", + "query-string": "^6.8.3", "react": "^19.2.7", "react-dom": "^19.2.7", "react-redux": "^9.3.0", diff --git a/src/interfaces/dde.d.ts b/src/interfaces/dde.d.ts index ee4ed7d..ebe0946 100644 --- a/src/interfaces/dde.d.ts +++ b/src/interfaces/dde.d.ts @@ -17,6 +17,7 @@ export interface IDdeStep1Config { studydesign: string; docversion: string; cdiscApiKey: string; + useCdiscLibraryProxy: boolean; cosmosversion: string; validate: boolean; validationReportPath: string; diff --git a/src/main/main.ts b/src/main/main.ts index be979a5..62449aa 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -8,16 +8,17 @@ import { shell, ipcMain, protocol, - net, + net } from 'electron'; import { installExtension, REDUX_DEVTOOLS, - REACT_DEVELOPER_TOOLS, + REACT_DEVELOPER_TOOLS } from 'electron-devtools-installer'; import StoreManager from '@/main/managers/storeManager'; import DefineXmlManager from '@/main/managers/defineXmlManager'; import DdeManager from '@/main/managers/ddeManager'; +import ClaMirrorManager from '@/main/managers/claMirrorManager'; import { resolveHtmlPath, writeToClipboard, parseArgs } from '@/main/utils'; import { FileInfo } from '@interfaces/common'; @@ -87,9 +88,9 @@ protocol.registerSchemesAsPrivileged([ standard: true, secure: true, supportFetchAPI: true, - stream: true, - }, - }, + stream: true + } + } ]); const RESOURCES_PATH = app.isPackaged @@ -109,8 +110,8 @@ const createWindow = async (openedFilePath?: string | null) => { webPreferences: { preload: app.isPackaged ? path.join(__dirname, 'preload.js') - : path.join(__dirname, '../../.erb/dll/preload.js'), - }, + : path.join(__dirname, '../../.erb/dll/preload.js') + } }); newWindow.loadURL(resolveHtmlPath('index.html')); @@ -160,7 +161,7 @@ const getFileInfo = async (fullPath: string): Promise => { filename: parsed.base, format: parsed.ext.replace(/^\./, ''), size: stats.size, - lastModified: stats.mtime.getTime(), + lastModified: stats.mtime.getTime() }; }; @@ -177,7 +178,7 @@ app try { const [redux, react] = await installExtension([ REDUX_DEVTOOLS, - REACT_DEVELOPER_TOOLS, + REACT_DEVELOPER_TOOLS ]); console.log(`Added Extensions: ${redux.name}, ${react.name}`); } catch (err) { @@ -203,14 +204,14 @@ app multiple?: boolean; initialFolder?: string; filters?: { name: string; extensions: string[] }[]; - }, + } ) => { const result = await dialog.showOpenDialog({ properties: options.multiple ? ['openFile', 'multiSelections'] : ['openFile'], defaultPath: options.initialFolder || undefined, - filters: options.filters, + filters: options.filters }); if (result.canceled) { @@ -218,16 +219,16 @@ app } return Promise.all( - result.filePaths.map((fullPath) => getFileInfo(fullPath)), + result.filePaths.map((fullPath) => getFileInfo(fullPath)) ); - }, + } ); ipcMain.handle( 'main:openDirectoryDialog', async (_event, initialFolder: string | null) => { const result = await dialog.showOpenDialog({ properties: ['openDirectory'], - defaultPath: initialFolder || undefined, + defaultPath: initialFolder || undefined }); if (result.canceled || result.filePaths.length === 0) { @@ -235,12 +236,12 @@ app } return result.filePaths[0]; - }, + } ); ipcMain.handle('main:openDefineXml', defineXmlManager.openDefineXml); ipcMain.handle( 'main:getDefineXmlContent', - defineXmlManager.getDefineXmlContent, + defineXmlManager.getDefineXmlContent ); ipcMain.handle('main:closeDefineXml', defineXmlManager.closeDefineXml); ipcMain.handle('main:runDdeStep', ddeManager.runStep); @@ -255,13 +256,13 @@ app ipcMain.handle('main:searchInPageNext', (_event, searchTerm) => { _event.sender.findInPage(searchTerm, { forward: true, - findNext: true, + findNext: true }); }); ipcMain.handle('main:searchInPagePrevious', (_event, searchTerm) => { _event.sender.findInPage(searchTerm, { forward: false, - findNext: true, + findNext: true }); }); ipcMain.handle('main:clearSearchResults', (_event) => { @@ -273,9 +274,9 @@ app path.join( RESOURCES_PATH, path.normalize( - decodeURIComponent(request.url.replace(/^media:\/\/\/?/, '')), - ), - ), + decodeURIComponent(request.url.replace(/^media:\/\/\/?/, '')) + ) + ) ); if (filePath.startsWith(RESOURCES_PATH)) { diff --git a/src/main/managers/claMirrorManager.ts b/src/main/managers/claMirrorManager.ts new file mode 100644 index 0000000..c525b01 --- /dev/null +++ b/src/main/managers/claMirrorManager.ts @@ -0,0 +1,561 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { app } from 'electron'; + +const express = require('express'); +const compression = require('compression'); +const cors = require('cors'); +const rateLimit = require('express-rate-limit'); +const { CdiscLibrary } = require('cla-wrapper'); + +export type ClaMirrorConfig = { + auth: { + apiKey: string; + }; + port: number; + debug: boolean; + cache: { + enabled: boolean; + includeFilter: string[]; + excludeFilter: string[]; + cacheFolder: string; + }; + cors: { + enabled: boolean; + origins: string[]; + }; + https?: { + enabled: boolean; + privateKeyPath?: string; + certificatePath?: string; + }; + ct: { + useNciSiteForCt: boolean; + nciSiteUrl: string; + enableNciProxy: boolean; + }; + rateLimit?: { + enabled: boolean; + windowMs: number; + max: number; + }; +}; + +const DEFAULT_EXCLUDE_FILTER = [ + 'health', + 'mdr/lastupdated', + 'mdr/products', + '.*/root/.*', + 'mdr/search/.*' +]; + +const DEFAULT_CORS_ORIGINS = ['*']; + +const wrapperRequest = async (params: string, cdiscLibrary: any) => { + const queryString = require('query-string'); + const paramsParsed = queryString.parse(params); + let { + format, + traffic, + productList, + product, + productDetails, + itemGroup, + listItemGroups + } = paramsParsed; + + if (!format) { + format = 'json'; + } + + if (traffic !== undefined) { + return cdiscLibrary.getTrafficStats(); + } + + if (productList !== undefined) { + return cdiscLibrary.getProductList(format); + } + + if (productDetails !== undefined) { + return cdiscLibrary.getProductDetails({ type: 'long', format }); + } + + if (product) { + const prodId = await cdiscLibrary.getProductIdByAlias(product); + if (!prodId) { + return `No such product (${product}). See /?productList or /?productDetails for the full list of products.`; + } + + const prd = await cdiscLibrary.getFullProduct(product, true); + + if (listItemGroups !== undefined) { + return prd.getItemGroups({ type: 'short', format }); + } + + if (itemGroup) { + const dataset = await prd.getItemGroup(itemGroup); + if (dataset !== undefined) { + return dataset.getFormattedItems(format); + } + + return `No such itemGroup (${itemGroup}). See /?product=XXX&listItemGroups to get the full list of itemGroups.`; + } + } + + return undefined; +}; + +class ClaCache { + private cacheFolder: string; + + private cachedIds: string[]; + + private excludeFilter: string[]; + + private includeFilter: string[]; + + constructor({ + cacheFolder, + cachedIds = [], + excludeFilter = [], + includeFilter = [] + }: { + cacheFolder: string; + cachedIds?: string[]; + excludeFilter?: string[]; + includeFilter?: string[]; + }) { + this.cacheFolder = cacheFolder; + this.cachedIds = cachedIds; + this.excludeFilter = excludeFilter; + this.includeFilter = includeFilter; + this.init = this.init.bind(this); + this.getRequestId = this.getRequestId.bind(this); + this.filterRequest = this.filterRequest.bind(this); + this.claMatch = this.claMatch.bind(this); + this.claPut = this.claPut.bind(this); + } + + async init() { + try { + await fs.mkdir(this.cacheFolder, { recursive: true }); + } catch (error) { + // Ignore if the directory already exists. + } + + let files: string[] = []; + try { + files = await fs.readdir(this.cacheFolder); + } catch (_error) { + return; + } + + this.cachedIds = files.map((file) => file.replace(/\.gz$/, '')); + } + + getRequestId(request: any) { + const shortenedUrl = request.url + .replace(/^.*?api\//, '') + .replace(/^.*?ftp1\/CDISC\//, '') + .replace('/root/', '/r/') + .replace('/cdash/', '/cd/') + .replace('/cdashig/', '/cdi/') + .replace('/sdtm/', '/s/') + .replace('/sdtmig/', '/si/') + .replace('/send/', '/se/') + .replace('/sendig/', '/sei/') + .replace('/adam/', '/a/') + .replace('/datasets/', '/d/') + .replace('/domains/', '/dm/') + .replace('/datastructures/', '/ds/') + .replace('/classes/', '/c/') + .replace('/variables/', '/v/') + .replace('/fields/', '/f/') + .replace('/varsets/', '/vs/') + .replace('/packages/', '/p/') + .replace('/codelists/', '/cl/') + .replace('/terms/', '/t/') + .replace('/scenarios/', '/s/') + .replace(/.*?\/mdr\//, '') + .replace(/\//g, '.') + .replace(/\s/g, '_'); + + if (request && request.headers) { + if (request.headers.Accept === 'application/json') { + return shortenedUrl; + } + if (request.headers.Accept === 'application/text/csv') { + return `${shortenedUrl}.csv`; + } + if (request.headers.Accept === 'application/vnd.ms-excel') { + return `${shortenedUrl}.excel`; + } + if (request.headers.Accept === 'text/html') { + return `${shortenedUrl}.html`; + } + if (request.headers.Accept === 'text/xml') { + return `${shortenedUrl}.xml`; + } + return undefined; + } + + return undefined; + } + + filterRequest(request: any) { + if (this.includeFilter.length > 0 || this.excludeFilter.length > 0) { + const endpoint = request.url.replace(/^.*?api\//, ''); + const excludeMatched = this.excludeFilter.some((regex) => + RegExp(`^${regex}$`).test(endpoint) + ); + if (excludeMatched) { + return true; + } + + if (this.includeFilter.length > 0) { + const includeMatched = this.includeFilter.some((regex) => + RegExp(`^${regex}$`).test(endpoint) + ); + if (!includeMatched) { + return true; + } + } + } + + return false; + } + + async claMatch(request: any) { + if (this.filterRequest(request)) { + return undefined; + } + + const id = this.getRequestId(request); + if (id === undefined) { + return undefined; + } + + if (!this.cachedIds.includes(id)) { + return undefined; + } + + const zippedData = await fs.readFile( + path.join(this.cacheFolder, `${id}.gz`) + ); + const Jszip = require('jszip'); + const zip = new Jszip(); + await zip.loadAsync(zippedData); + + if (Object.keys(zip.files).includes('response.json')) { + const result = await zip.file('response.json').async('string'); + return JSON.parse(result); + } + + return undefined; + } + + async claPut(request: any, response: any) { + if (this.filterRequest(request)) { + return; + } + + const id = await this.getRequestId(request); + if (!id) { + return; + } + + const data: { headers: any; body?: string } = { headers: response.headers }; + if (data.headers['content-type']?.startsWith('application/json')) { + data.body = JSON.stringify(JSON.parse(response.body)); + } else { + data.body = response.body; + } + + const Jszip = require('jszip'); + const zip = new Jszip(); + zip.file('response.json', JSON.stringify(data)); + const zippedData = await zip.generateAsync({ + type: 'nodebuffer', + compression: 'DEFLATE', + compressionOptions: { level: 7 } + }); + + await fs.writeFile(path.join(this.cacheFolder, `${id}.gz`), zippedData); + this.cachedIds.push(id); + } +} + +export const buildClaMirrorConfig = ( + userDataDir: string, + apiKey = process.env.CDISC_API_KEY || '' +): ClaMirrorConfig => { + const cacheFolder = path.join(userDataDir, 'cdiscCache'); + + return { + auth: { + apiKey + }, + port: 4600, + debug: false, + cache: { + enabled: true, + includeFilter: [], + excludeFilter: DEFAULT_EXCLUDE_FILTER, + cacheFolder + }, + cors: { + enabled: false, + origins: DEFAULT_CORS_ORIGINS + }, + ct: { + useNciSiteForCt: false, + nciSiteUrl: 'https://evs.nci.nih.gov/ftp1/CDISC', + enableNciProxy: false + }, + rateLimit: { + enabled: false, + windowMs: 60000, + max: 60 + } + }; +}; + +class ClaMirrorManager { + private appDataDir: string; + + private config: ClaMirrorConfig | null; + + private server: any; + + constructor(appDataDir = app.getPath('userData')) { + this.appDataDir = appDataDir; + this.config = null; + this.server = null; + } + + private getConfig(apiKeyOverride?: string): ClaMirrorConfig { + const apiKey = apiKeyOverride || process.env.CDISC_API_KEY || ''; + if (!this.config || this.config.auth.apiKey !== apiKey) { + this.config = buildClaMirrorConfig(this.appDataDir, apiKey); + } + return this.config; + } + + public async start(apiKeyOverride?: string): Promise { + if (this.server) { + return this.server; + } + + const config = this.getConfig( + apiKeyOverride || process.env.CDISC_API_KEY || '' + ); + const cacheEnabled = config.cache && config.cache.enabled; + const cacheDir = + config.cache.cacheFolder || path.join(this.appDataDir, 'cdiscCache'); + await fs.mkdir(cacheDir, { recursive: true }); + const expressApp = express(); + + expressApp.use((req: any, res: any, next: any) => { + const remoteAddress = req.socket?.remoteAddress || req.ip || ''; + const isLocalhost = + remoteAddress === '::1' || + remoteAddress === '::ffff:127.0.0.1' || + remoteAddress === '127.0.0.1' || + remoteAddress.startsWith('127.') || + remoteAddress.startsWith('::ffff:127.'); + + if (!isLocalhost) { + res.status(403).send('Forbidden: localhost only'); + return; + } + + next(); + }); + + if (cacheEnabled) { + const claCache = new ClaCache({ + cacheFolder: cacheDir, + excludeFilter: config.cache.excludeFilter, + includeFilter: config.cache.includeFilter + }); + await claCache.init(); + + const cl = new CdiscLibrary({ + apiKey: config.auth.apiKey, + useNciSiteForCt: config.ct.useNciSiteForCt, + nciSiteUrl: config.ct.nciSiteUrl, + cache: { + match: (request: any) => claCache.claMatch(request), + put: (request: any, response: any) => + claCache.claPut(request, response) + } + }); + + expressApp.use( + compression({ + filter: (req: any, res: any) => { + if (req.headers['x-no-compression']) { + return false; + } + if (typeof req.headers['accept-encoding'] === 'string') { + return req.headers['accept-encoding'] + .split(',') + .map((item: string) => item.trim()) + .includes('gzip') + ? compression.filter(req, res) + : false; + } + return false; + } + }) + ); + + if (config.rateLimit && config.rateLimit.enabled) { + const rateLimitConfig = { + ...config.rateLimit, + enabled: undefined, + message: + 'You have reached the number of allowed requests. Please wait.' + }; + expressApp.use(rateLimit(rateLimitConfig)); + } + + if (config.cors && config.cors.enabled) { + const { origins } = config.cors; + let corsOptions: any; + if ( + !( + Array.isArray(origins) && + origins.length === 1 && + origins[0] === '*' + ) + ) { + corsOptions = { + origin: (origin: string | undefined, callback: any) => { + if (origins.includes(origin || '')) { + callback(null, true); + } else { + callback(new Error('Not allowed by CORS')); + } + } + }; + } + expressApp.use(cors(corsOptions)); + } + + expressApp.use('/', async (req: any, res: any) => { + try { + if (req.url.startsWith('/api/')) { + const endpoint = req.url.replace(/^\/api/, ''); + const headers: Record = {}; + + if ( + /application\/(json|vnd\.ms-excel)|text\/csv/i.test( + req.headers.accept + ) + ) { + headers.Accept = req.headers.accept; + } else if (/&format=csv/i.test(endpoint)) { + const nextEndpoint = endpoint.replace(/&format=csv/i, ''); + headers.Accept = 'text/csv'; + req.url = `/api${nextEndpoint}`; + } else if (/&format=xls/i.test(endpoint)) { + const nextEndpoint = endpoint.replace(/&format=xls/i, ''); + headers.Accept = 'application/vnd.ms-excel'; + req.url = `/api${nextEndpoint}`; + } else if (/&format=json/i.test(endpoint)) { + const nextEndpoint = endpoint.replace(/&format=json/i, ''); + req.url = `/api${nextEndpoint}`; + } + + if (!config.auth.apiKey && req.headers['api-key']) { + headers['api-key'] = req.headers['api-key']; + } + + const response = await cl.coreObject.apiRequest(endpoint, { + headers, + returnRaw: true + }); + + if ( + response.statusCode !== 200 && + response.statusCode !== undefined + ) { + res.sendStatus(response.statusCode); + return; + } + + if ( + response.headers['content-type'] === 'application/vnd.ms-excel' + ) { + const fileName = `${endpoint + .replace(/.*\/(.+\/.+)/, '$1') + .replace(/\W/g, '.')}.xls`; + res.setHeader( + 'Content-Disposition', + `attachment; filename=${fileName}` + ); + res.setHeader('Content-Type', response.headers['content-type']); + res.setHeader( + 'Transfer-Encoding', + response.headers['transfer-encoding'] + ); + res.send(Buffer.from(response.body, 'binary')); + return; + } + + res.setHeader('Content-Type', response.headers['content-type']); + res.send(response.body); + return; + } + + if (req.url.startsWith('/?')) { + const response = await wrapperRequest( + req.url.replace(/^\//, ''), + cl + ); + res.send(response && response.body ? response.body : response); + return; + } + + if (req.url.startsWith('/nciSite/') && config.ct.enableNciProxy) { + const acceptType = req.url.endsWith('.xml') + ? 'text/xml' + : 'text/html'; + const response = await cl.coreObject.apiRequest(req.url, { + headers: { Accept: acceptType }, + returnRaw: true + }); + res.send(response.body); + return; + } + + res.status(404).send('Not found'); + } catch (error: any) { + console.log( + `Error when running a request for ${req.url}: ${error.message}` + ); + res.status(500).send('Internal Server Error'); + } + }); + } + + const port = config.port || 4600; + this.server = expressApp.listen(port, '127.0.0.1', () => { + console.log( + `CDISC Library API Mirror is listening on 127.0.0.1:${port} using HTTP protocol` + ); + }); + + return this.server; + } + + public stop() { + if (this.server) { + this.server.close(); + this.server = null; + } + } +} + +export default ClaMirrorManager; diff --git a/src/main/managers/ddeManager.ts b/src/main/managers/ddeManager.ts index cb4c78c..c11ca71 100644 --- a/src/main/managers/ddeManager.ts +++ b/src/main/managers/ddeManager.ts @@ -3,10 +3,11 @@ import { ChildProcessWithoutNullStreams, execFile, spawn } from 'child_process'; import fs from 'fs'; import path from 'path'; import readline from 'readline'; +import ClaMirrorManager from '@/main/managers/claMirrorManager'; import { DdeRunRequest, DdeRuntimePaths, - PythonCheckResult, + PythonCheckResult } from '@interfaces/common'; interface DdeManagerOptions { @@ -23,8 +24,11 @@ class DdeManager { private readonly runningProcesses = new Map(); + private readonly claMirrorManager: ClaMirrorManager; + constructor({ resourcesPath }: DdeManagerOptions) { this.resourcesPath = resourcesPath; + this.claMirrorManager = new ClaMirrorManager(); } private getDdeScriptsPath(runtimePaths?: DdeRuntimePaths) { @@ -37,7 +41,7 @@ class DdeManager { private getPythonVenvPath( env?: Record, - runtimePaths?: DdeRuntimePaths, + runtimePaths?: DdeRuntimePaths ) { if (runtimePaths?.pythonVenvPath) { return runtimePaths.pythonVenvPath; @@ -52,7 +56,7 @@ class DdeManager { private getPythonCommand( env?: Record, - runtimePaths?: DdeRuntimePaths, + runtimePaths?: DdeRuntimePaths ) { if (env?.DDE_PYTHON_EXE) { return env.DDE_PYTHON_EXE; @@ -75,12 +79,12 @@ class DdeManager { private getPythonEnv( env?: Record, - runtimePaths?: DdeRuntimePaths, + runtimePaths?: DdeRuntimePaths ) { const pythonEnv = { ...process.env, ...env, - CDISC_API_KEY: env?.CDISC_API_KEY || process.env.CDISC_API_KEY, + CDISC_API_KEY: env?.CDISC_API_KEY || process.env.CDISC_API_KEY } as Record; const venvPath = this.getPythonVenvPath(env, runtimePaths); @@ -107,7 +111,7 @@ class DdeManager { private getScriptPath( step: DdeRunRequest['step'], - runtimePaths?: DdeRuntimePaths, + runtimePaths?: DdeRuntimePaths ) { const baseScriptsPath = this.getDdeScriptsPath(runtimePaths); @@ -119,7 +123,7 @@ class DdeManager { baseScriptsPath, 'generators', 'define', - 'define_generator.py', + 'define_generator.py' ); } @@ -136,7 +140,7 @@ class DdeManager { private formatCommandLine( pythonCommand: string, scriptPath: string, - args: string[], + args: string[] ) { const quoteArg = (value: string) => /\s/.test(value) ? `"${value.replace(/"/g, '\\"')}"` : value; @@ -146,7 +150,7 @@ class DdeManager { public runStep = async ( event: IpcMainInvokeEvent, - request: DdeRunRequest, + request: DdeRunRequest ): Promise<{ started: boolean } | { error: string }> => { const scriptPath = this.getScriptPath(request.step, request.runtimePaths); if (!fs.existsSync(scriptPath)) { @@ -155,39 +159,46 @@ class DdeManager { const pythonCommand = this.getPythonCommand( request.env, - request.runtimePaths, + request.runtimePaths ); const outputPath = this.getOutputPath(request); const definePath = request.step === 'step3' ? outputPath : undefined; const commandLine = this.formatCommandLine( pythonCommand, scriptPath, - request.args, + request.args ); + const shouldUseProxy = request.args.includes('--base_api_url'); + if (shouldUseProxy) { + await this.claMirrorManager.start( + request.env?.CDISC_API_KEY || process.env.CDISC_API_KEY || '' + ); + } + const child = spawn(pythonCommand, ['-u', scriptPath, ...request.args], { cwd: path.dirname(scriptPath), env: { ...this.getPythonEnv(request.env, request.runtimePaths), - PYTHONUNBUFFERED: '1', - }, + PYTHONUNBUFFERED: '1' + } }); this.runningProcesses.set(request.id, { child, - stopRequested: false, + stopRequested: false }); // If there is a CDISC API key in the command, replace it with a placeholder in the log output to avoid exposing sensitive information. const sanitizedCommandLine = commandLine.replace( /(--cdisc_api_key\s+)(\S+)/, - '$1 *****', + '$1 *****' ); event.sender.send('renderer:ddeProgress', { id: request.id, step: request.step, status: 'starting', - line: `>_ ${sanitizedCommandLine}\n`, + line: `>_ ${sanitizedCommandLine}\n` }); const forwardOutput = (stream: NodeJS.ReadableStream) => { @@ -197,7 +208,7 @@ class DdeManager { id: request.id, step: request.step, status: 'running', - line, + line }); }); }; @@ -206,6 +217,9 @@ class DdeManager { forwardOutput(child.stderr); child.on('error', (error) => { + if (shouldUseProxy) { + this.claMirrorManager.stop(); + } this.runningProcesses.delete(request.id); event.sender.send('renderer:ddeProgress', { id: request.id, @@ -213,11 +227,14 @@ class DdeManager { status: 'error', error: error.message, outputPath, - definePath, + definePath }); }); child.on('exit', (exitCode) => { + if (shouldUseProxy) { + this.claMirrorManager.stop(); + } const current = this.runningProcesses.get(request.id); this.runningProcesses.delete(request.id); const status = @@ -238,7 +255,7 @@ class DdeManager { error: status === 'error' ? `Process exited with code ${exitCode}` - : undefined, + : undefined }); }); @@ -247,7 +264,7 @@ class DdeManager { public stopStep = async ( _event: IpcMainInvokeEvent, - id: string, + id: string ): Promise => { const current = this.runningProcesses.get(id); if (!current) { @@ -260,7 +277,7 @@ class DdeManager { public checkPython = async ( _event: IpcMainInvokeEvent, - runtimePaths?: DdeRuntimePaths, + runtimePaths?: DdeRuntimePaths ): Promise => { const pythonCommand = this.getPythonCommand(undefined, runtimePaths); const modules = [ @@ -269,7 +286,7 @@ class DdeManager { 'odmlib', 'defineutils', 'yaml', - 'dotenv', + 'dotenv' ]; const script = [ @@ -277,7 +294,7 @@ class DdeManager { `mods = ${JSON.stringify(modules)}`, 'missing = [name for name in mods if importlib.util.find_spec(name) is None]', 'print(sys.version.split()[0])', - 'print("|".join(missing))', + 'print("|".join(missing))' ].join('; '); return new Promise((resolve) => { @@ -292,7 +309,7 @@ class DdeManager { pythonCommand, version: null, missingModules: [], - error: stderr.trim() || error.message, + error: stderr.trim() || error.message }); return; } @@ -309,9 +326,9 @@ class DdeManager { pythonCommand, version: versionLine || null, missingModules, - error: null, + error: null }); - }, + } ); }); }; diff --git a/src/renderer/components/DdeStep1/index.tsx b/src/renderer/components/DdeStep1/index.tsx index 347e026..baec814 100644 --- a/src/renderer/components/DdeStep1/index.tsx +++ b/src/renderer/components/DdeStep1/index.tsx @@ -491,6 +491,21 @@ const DdeStep1: React.FC = () => { v2 + + + updateConfig({ + useCdiscLibraryProxy: event.target.checked, + }) + } + /> + } + label="Use cache" + /> + diff --git a/src/renderer/redux/initialState.ts b/src/renderer/redux/initialState.ts index baea8d9..b0cb462 100644 --- a/src/renderer/redux/initialState.ts +++ b/src/renderer/redux/initialState.ts @@ -49,6 +49,7 @@ export const dde: IDdeState = { studydesign: '0', docversion: '0', cdiscApiKey: '', + useCdiscLibraryProxy: false, cosmosversion: 'v2', validate: false, validationReportPath: '', diff --git a/src/renderer/utils/buildLoaderArgs.ts b/src/renderer/utils/buildLoaderArgs.ts index 6ece54f..f61766b 100644 --- a/src/renderer/utils/buildLoaderArgs.ts +++ b/src/renderer/utils/buildLoaderArgs.ts @@ -17,12 +17,15 @@ export const buildLoaderArgs = (config: IDdeStep1Config): string[] => { '--docversion', config.docversion, '--cosmosversion', - config.cosmosversion, + config.cosmosversion ]; if (config.cdiscApiKey) { args.push('--cdisc_api_key', config.cdiscApiKey); } + if (config.useCdiscLibraryProxy) { + args.push('--base_api_url', 'http://localhost:4600/api'); + } if (config.validate) { args.push('--validate'); }