diff --git a/CEO/.idea/.gitignore b/CEO/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/CEO/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/CEO/.idea/.name b/CEO/.idea/.name deleted file mode 100644 index d8fcf6c..0000000 --- a/CEO/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -reset_password.js \ No newline at end of file diff --git a/CEO/.idea/jsLibraryMappings.xml b/CEO/.idea/jsLibraryMappings.xml deleted file mode 100644 index d23208f..0000000 --- a/CEO/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/CEO/.idea/modules.xml b/CEO/.idea/modules.xml deleted file mode 100644 index 202146e..0000000 --- a/CEO/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/CEO/.idea/vcs.xml b/CEO/.idea/vcs.xml deleted file mode 100644 index 62bd7a0..0000000 --- a/CEO/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/CEO/package-lock.json b/CEO/package-lock.json deleted file mode 100644 index 05e8e3b..0000000 --- a/CEO/package-lock.json +++ /dev/null @@ -1,6621 +0,0 @@ -{ - "name": "ceoapp", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "ceoapp", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "dotenv": "^16.4.5", - "ping": "^0.4.4", - "proper-lockfile": "^4.1.2", - "uuid": "^10.0.0" - }, - "devDependencies": { - "@electron-forge/cli": "^6.0.0", - "@electron-forge/maker-deb": "^6.0.0", - "@electron-forge/maker-rpm": "^6.0.0", - "@electron-forge/maker-squirrel": "^6.0.0", - "@electron-forge/maker-zip": "^6.0.0", - "@types/ping": "^0.4.4", - "@types/proper-lockfile": "^4.1.4", - "@types/uuid": "^10.0.0", - "check-disk-space": "^3.4.0", - "copyfiles": "^2.4.1", - "del-cli": "^5.0.0", - "electron": "^33.0.2", - "typescript": "^5.6.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@electron-forge/cli": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/cli/-/cli-6.4.2.tgz", - "integrity": "sha512-bM6YVTV0uUEpIL1jkpARlSm4Li26XZn+avC/lyTdpPqnd65T/oXZNkrAD+2Jb0RlgplOaM21qWm7ybtvKDGDyA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.electron-forge-cli?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "MIT", - "dependencies": { - "@electron-forge/core": "6.4.2", - "@electron-forge/shared-types": "6.4.2", - "@electron/get": "^2.0.0", - "chalk": "^4.0.0", - "commander": "^4.1.1", - "debug": "^4.3.1", - "fs-extra": "^10.0.0", - "listr2": "^5.0.3", - "semver": "^7.2.1" - }, - "bin": { - "electron-forge": "dist/electron-forge.js", - "electron-forge-vscode-nix": "script/vscode.sh", - "electron-forge-vscode-win": "script/vscode.cmd" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/core": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/core/-/core-6.4.2.tgz", - "integrity": "sha512-VtrFZ1Q7NG1ov0jJO/tUvUiYdWZ0Y31xw762is/jfpRPD6V/soOpwJJAoWoPK9TZVkTm2pkS8S5LikCMbNCLxw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.electron-forge-core?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "MIT", - "dependencies": { - "@electron-forge/core-utils": "6.4.2", - "@electron-forge/maker-base": "6.4.2", - "@electron-forge/plugin-base": "6.4.2", - "@electron-forge/publisher-base": "6.4.2", - "@electron-forge/shared-types": "6.4.2", - "@electron-forge/template-base": "6.4.2", - "@electron-forge/template-vite": "6.4.2", - "@electron-forge/template-vite-typescript": "6.4.2", - "@electron-forge/template-webpack": "6.4.2", - "@electron-forge/template-webpack-typescript": "6.4.2", - "@electron/get": "^2.0.0", - "@electron/rebuild": "^3.2.10", - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.3.1", - "electron-packager": "^17.1.2", - "fast-glob": "^3.2.7", - "filenamify": "^4.1.0", - "find-up": "^5.0.0", - "fs-extra": "^10.0.0", - "got": "^11.8.5", - "interpret": "^3.1.1", - "listr2": "^5.0.3", - "lodash": "^4.17.20", - "log-symbols": "^4.0.0", - "node-fetch": "^2.6.7", - "progress": "^2.0.3", - "rechoir": "^0.8.0", - "resolve-package": "^1.0.1", - "semver": "^7.2.1", - "source-map-support": "^0.5.13", - "sudo-prompt": "^9.1.1", - "username": "^5.1.0", - "yarn-or-npm": "^3.0.1" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/core-utils": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/core-utils/-/core-utils-6.4.2.tgz", - "integrity": "sha512-CjB3aakmRsXAMMDYc8PxNTMf4FdI29y4PErfv7eCXlL5oo3JW0VSKZIV7R8/Po0S0got85q2kmhZgCKuxL1BNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@electron/rebuild": "^3.2.10", - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.3.1", - "find-up": "^5.0.0", - "fs-extra": "^10.0.0", - "log-symbols": "^4.0.0", - "semver": "^7.2.1", - "yarn-or-npm": "^3.0.1" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/maker-base": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-base/-/maker-base-6.4.2.tgz", - "integrity": "sha512-zW3GH+LqDK9nxQmQEFkJPR8RqiX0lVk6a4mXll3ngujN1fPevO4ivUAWmaEVeC1dH/hXbN7s9m0S6a37MigftQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "fs-extra": "^10.0.0", - "which": "^2.0.2" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/maker-deb": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-deb/-/maker-deb-6.4.2.tgz", - "integrity": "sha512-tlV8ffivgBP94vtYXgAeXgzeKCaRyLuWH9LT8PQW1QrYbAFpCMmuwk/zFaJkyMklImCWmDFTPYMEqdEJGd7Npg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "6.4.2", - "@electron-forge/shared-types": "6.4.2" - }, - "engines": { - "node": ">= 14.17.5" - }, - "optionalDependencies": { - "electron-installer-debian": "^3.2.0" - } - }, - "node_modules/@electron-forge/maker-rpm": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-rpm/-/maker-rpm-6.4.2.tgz", - "integrity": "sha512-+hfbY5pYbAer0y07OtOzVgVBHoTRmemqqZ//T0mKJpyK2ThHKGTvyW8FFlr5jlQs5LoDCM2WHKE8oGtRhivsMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "6.4.2", - "@electron-forge/shared-types": "6.4.2" - }, - "engines": { - "node": ">= 14.17.5" - }, - "optionalDependencies": { - "electron-installer-redhat": "^3.2.0" - } - }, - "node_modules/@electron-forge/maker-squirrel": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-squirrel/-/maker-squirrel-6.4.2.tgz", - "integrity": "sha512-ukK3RcFaBrQXUzR52PsHxfwDq5XKSnj6A1kkXiyHWqgj+HIU97prBScBb5JRtasPvYN+nDdQO2vlInsLaqcx9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "6.4.2", - "@electron-forge/shared-types": "6.4.2", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 14.17.5" - }, - "optionalDependencies": { - "electron-winstaller": "^5.0.0" - } - }, - "node_modules/@electron-forge/maker-zip": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/maker-zip/-/maker-zip-6.4.2.tgz", - "integrity": "sha512-k2nfhhnxcYbUS7rCKCisuqEalxtH9l73+lrtfL0aQZiE/BLbDXyNckDIDOPvX0tBEg62nVzUdJonZwOhZVvAMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "6.4.2", - "@electron-forge/shared-types": "6.4.2", - "cross-zip": "^4.0.0", - "fs-extra": "^10.0.0", - "got": "^11.8.5" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/plugin-base": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/plugin-base/-/plugin-base-6.4.2.tgz", - "integrity": "sha512-g6AAtQ7fZ94djBmwcnWasQ8xgaNVNjgaQ00GLK0NkmQ7n0PNbsnlMDuw9vdfTiL6WaLg5nxNSYc9bFJP/rtyeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/publisher-base": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/publisher-base/-/publisher-base-6.4.2.tgz", - "integrity": "sha512-Tnf9O8MFzdT1gsb5EDDaQUoslt7gUuUywtsr+lT/fpBlBQbei2fvioTwvZ1Q1cmsKnld7XhRh6unfgdWLTZzgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/shared-types": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/shared-types/-/shared-types-6.4.2.tgz", - "integrity": "sha512-DKOUMsdTXZIq8XiqY0Hi3C+dam/JKUnvfBjwcUeyZqPdgEE1qry8xZmmjorXuLrRf1Jq8rhxYGQInSK4af0QYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/rebuild": "^3.2.10", - "electron-packager": "^17.1.2", - "listr2": "^5.0.3" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/template-base": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/template-base/-/template-base-6.4.2.tgz", - "integrity": "sha512-vsQh+64Fr2Vxg6k8DAahWq4MAdB2F2qTig+LgIJENv8ksbzC1YIq05SBAS/g2674cdr7WdwyukMy2rgxe3rhnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.3.1", - "fs-extra": "^10.0.0", - "username": "^5.1.0" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/template-vite": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite/-/template-vite-6.4.2.tgz", - "integrity": "sha512-NX7jHRblBmIqufMbqWgpI/VnpgF/qMSTq9ZPmDSXamBhid336MC6+DoWzDpXceQZEp0m/jpMLR04ynr8O4jGlg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@electron-forge/template-base": "6.4.2", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - } - }, - "node_modules/@electron-forge/template-vite-typescript": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/template-vite-typescript/-/template-vite-typescript-6.4.2.tgz", - "integrity": "sha512-h3pn6onvC/nLglmJuelYU82Qzrh0l6MqvbBGoT39bbDoRLIqmlhWTWppHgDJVXAGrSoH+9BEpptipeBQWirFwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@electron-forge/template-base": "6.4.2", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - } - }, - "node_modules/@electron-forge/template-webpack": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack/-/template-webpack-6.4.2.tgz", - "integrity": "sha512-9QYr/td4cmnGOj8UF25W6An/eI+JXj9T/b+KFybL3cQ87H1yrQOn2T84Bm5/JaB4SPdIu4FdKRjqwR7C7R0g2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@electron-forge/template-base": "6.4.2", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron-forge/template-webpack-typescript": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-6.4.2.tgz", - "integrity": "sha512-MPAZQ4v6piCED7NT1LTVQf61o6Eg/laNoKbhbrFBSH1i20OUwbtV2MLj6Op292ynI9+1qdHKmFgctr6qPTCAQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "6.4.2", - "@electron-forge/template-base": "6.4.2", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron/asar": { - "version": "3.2.17", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.17.tgz", - "integrity": "sha512-OcWImUI686w8LkghQj9R2ynZ2ME693Ek6L1SiaAgqGKzBaTIZw3fHDqN82Rcl+EU1Gm9EgkJ5KLIY/q5DCRbbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@electron/asar/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@electron/asar/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@electron/get/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@electron/get/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/get/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@electron/get/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@electron/node-gyp": { - "version": "10.2.0-electron.1", - "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "integrity": "sha512-4MSBTT8y07YUDqf69/vSh80Hh791epYqGtWHO3zSKhYFwQg+gx9wi1PqbqP6YqC4WMsNxZ5l9oDmnWdK5pfCKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^8.1.0", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.2.1", - "nopt": "^6.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/notarize": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-1.2.4.tgz", - "integrity": "sha512-W5GQhJEosFNafewnS28d3bpQ37/s91CDWqxVchHfmv2dQSTWpOzNlUVQwYzC1ay5bChRV/A9BTL68yj0Pa+TSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "compare-version": "^0.1.2", - "debug": "^4.3.4", - "fs-extra": "^10.0.0", - "isbinaryfile": "^4.0.8", - "minimist": "^1.2.6", - "plist": "^3.0.5" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@electron/rebuild": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.1.tgz", - "integrity": "sha512-sKGD+xav4Gh25+LcLY0rjIwcCFTw+f/HU1pB48UVbwxXXRGaXEqIH0AaYKN46dgd/7+6kuiDXzoyAEvx1zCsdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", - "ora": "^5.1.0", - "read-binary-file-arch": "^1.0.6", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/universal": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", - "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", - "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/@electron/universal/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/windows-sign": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.0.tgz", - "integrity": "sha512-5zfLHfD6kGgsXzuYlKwlWWO8w6dboKy4dhd7rGnR4rQYumuDgPAF2TYjEa8LUi89KdHxtDy2btq02KvbjhK9Iw==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "dependencies": { - "cross-dirname": "^0.1.0", - "debug": "^4.3.4", - "fs-extra": "^11.1.1", - "minimist": "^1.2.8", - "postject": "^1.0.0-alpha.6" - }, - "bin": { - "electron-windows-sign": "bin/electron-windows-sign.js" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/windows-sign/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.17.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz", - "integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ping": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@types/ping/-/ping-0.4.4.tgz", - "integrity": "sha512-ifvo6w2f5eJYlXm+HiVx67iJe8WZp87sfa683nlqED5Vnt9Z93onkokNoWqOG21EaE8fMxyKPobE+mkPEyxsdw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/proper-lockfile": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz", - "integrity": "sha512-uo2ABllncSqg9F1D4nugVl9v93RmjxF6LJzQLMLDdPaXCUIDPeOJ21Gbqi43xNKzBi/WQ0Q0dICqufzQbMjipQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "*" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.5.tgz", - "integrity": "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asar": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", - "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", - "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "chromium-pickle-js": "^0.2.0", - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" - }, - "optionalDependencies": { - "@types/glob": "^7.1.1" - } - }, - "node_modules/asar/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/asar/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/author-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", - "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", - "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacache/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cacache/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cacache/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-disk-space": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/check-disk-space/-/check-disk-space-3.4.0.tgz", - "integrity": "sha512-drVkSqfwA+TvuEhFipiR1OC9boEGZL5RrWvVsOthdcvQNXyCCuKkEiTOTXZ7qxSf/GLwq4GvzfrQD/Wz325hgw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/chromium-pickle-js": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/compare-version": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/copyfiles": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", - "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^7.0.5", - "minimatch": "^3.0.3", - "mkdirp": "^1.0.4", - "noms": "0.0.0", - "through2": "^2.0.1", - "untildify": "^4.0.0", - "yargs": "^16.1.0" - }, - "bin": { - "copyfiles": "copyfiles", - "copyup": "copyfiles" - } - }, - "node_modules/copyfiles/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/copyfiles/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/copyfiles/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/copyfiles/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-dirname": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", - "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn-windows-exe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/cross-spawn-windows-exe/-/cross-spawn-windows-exe-1.2.0.tgz", - "integrity": "sha512-mkLtJJcYbDCxEG7Js6eUnUNndWjyUZwJ3H7bErmmtOYU/Zb99DyUkpamuIZE0b3bhmJyZ7D90uS6f+CGxRRjOw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-cross-spawn-windows-exe?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "@malept/cross-spawn-promise": "^1.1.0", - "is-wsl": "^2.2.0", - "which": "^2.0.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cross-spawn-windows-exe/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cross-zip": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cross-zip/-/cross-zip-4.0.1.tgz", - "integrity": "sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "engines": { - "node": ">=12.10" - } - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/del/-/del-7.1.0.tgz", - "integrity": "sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^13.1.2", - "graceful-fs": "^4.2.10", - "is-glob": "^4.0.3", - "is-path-cwd": "^3.0.0", - "is-path-inside": "^4.0.0", - "p-map": "^5.5.0", - "rimraf": "^3.0.2", - "slash": "^4.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del-cli": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/del-cli/-/del-cli-5.1.0.tgz", - "integrity": "sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^7.1.0", - "meow": "^10.1.3" - }, - "bin": { - "del": "cli.js", - "del-cli": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/dir-compare": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", - "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/electron": { - "version": "33.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-33.2.0.tgz", - "integrity": "sha512-PVw1ICAQDPsnnsmpNFX/b1i/49h67pbSPxuIENd9K9WpGO1tsRaQt+K2bmXqTuoMJsbzIc75Ce8zqtuwBPqawA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 12.20.55" - } - }, - "node_modules/electron-installer-common": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/electron-installer-common/-/electron-installer-common-0.10.3.tgz", - "integrity": "sha512-mYbP+6i+nHMIm0WZHXgGdmmXMe+KXncl6jZYQNcCF9C1WsNA9C5SZ2VP4TLQMSIoFO+X4ugkMEA5uld1bmyEvA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@malept/cross-spawn-promise": "^1.0.0", - "asar": "^3.0.0", - "debug": "^4.1.1", - "fs-extra": "^9.0.0", - "glob": "^7.1.4", - "lodash": "^4.17.15", - "parse-author": "^2.0.0", - "semver": "^7.1.1", - "tmp-promise": "^3.0.2" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "url": "https://github.com/electron-userland/electron-installer-common?sponsor=1" - }, - "optionalDependencies": { - "@types/fs-extra": "^9.0.1" - } - }, - "node_modules/electron-installer-common/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-common/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-common/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/electron-installer-debian": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/electron-installer-debian/-/electron-installer-debian-3.2.0.tgz", - "integrity": "sha512-58ZrlJ1HQY80VucsEIG9tQ//HrTlG6sfofA3nRGr6TmkX661uJyu4cMPPh6kXW+aHdq/7+q25KyQhDrXvRL7jw==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@malept/cross-spawn-promise": "^1.0.0", - "debug": "^4.1.1", - "electron-installer-common": "^0.10.2", - "fs-extra": "^9.0.0", - "get-folder-size": "^2.0.1", - "lodash": "^4.17.4", - "word-wrap": "^1.2.3", - "yargs": "^16.0.2" - }, - "bin": { - "electron-installer-debian": "src/cli.js" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-installer-debian/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-debian/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/electron-installer-debian/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-debian/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-debian/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-redhat": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/electron-installer-redhat/-/electron-installer-redhat-3.4.0.tgz", - "integrity": "sha512-gEISr3U32Sgtj+fjxUAlSDo3wyGGq6OBx7rF5UdpIgbnpUvMN4W5uYb0ThpnAZ42VEJh/3aODQXHbFS4f5J3Iw==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@malept/cross-spawn-promise": "^1.0.0", - "debug": "^4.1.1", - "electron-installer-common": "^0.10.2", - "fs-extra": "^9.0.0", - "lodash": "^4.17.15", - "word-wrap": "^1.2.3", - "yargs": "^16.0.2" - }, - "bin": { - "electron-installer-redhat": "src/cli.js" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-installer-redhat/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-redhat/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/electron-installer-redhat/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-redhat/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-redhat/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-packager": { - "version": "17.1.2", - "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-17.1.2.tgz", - "integrity": "sha512-XofXdikjYI7MVBcnXeoOvRR+yFFFHOLs3J7PF5KYQweigtgLshcH4W660PsvHr4lYZ03JBpLyEcUB8DzHZ+BNw==", - "deprecated": "Please use @electron/packager moving forward. There is no API change, just a package name change", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@electron/asar": "^3.2.1", - "@electron/get": "^2.0.0", - "@electron/notarize": "^1.2.3", - "@electron/osx-sign": "^1.0.5", - "@electron/universal": "^1.3.2", - "cross-spawn-windows-exe": "^1.2.0", - "debug": "^4.0.1", - "extract-zip": "^2.0.0", - "filenamify": "^4.1.0", - "fs-extra": "^11.1.0", - "galactus": "^1.0.0", - "get-package-info": "^1.0.0", - "junk": "^3.1.0", - "parse-author": "^2.0.0", - "plist": "^3.0.0", - "rcedit": "^3.0.1", - "resolve": "^1.1.6", - "semver": "^7.1.3", - "yargs-parser": "^21.1.1" - }, - "bin": { - "electron-packager": "bin/electron-packager.js" - }, - "engines": { - "node": ">= 14.17.5" - }, - "funding": { - "url": "https://github.com/electron/electron-packager?sponsor=1" - } - }, - "node_modules/electron-packager/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/electron-winstaller": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", - "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@electron/asar": "^3.2.1", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.21", - "temp": "^0.9.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "@electron/windows-sign": "^1.1.2" - } - }, - "node_modules/electron-winstaller/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/electron-winstaller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optional": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-winstaller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", - "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flora-colossus": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flora-colossus/-/flora-colossus-2.0.0.tgz", - "integrity": "sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "fs-extra": "^10.1.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/galactus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/galactus/-/galactus-1.0.0.tgz", - "integrity": "sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "flora-colossus": "^2.0.0", - "fs-extra": "^10.1.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/gar": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", - "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-folder-size": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-folder-size/-/get-folder-size-2.0.1.tgz", - "integrity": "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "gar": "^1.0.4", - "tiny-each-async": "2.0.3" - }, - "bin": { - "get-folder-size": "bin/get-folder-size" - } - }, - "node_modules/get-installed-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/get-installed-path/-/get-installed-path-2.1.1.tgz", - "integrity": "sha512-Qkn9eq6tW5/q9BDVdMpB8tOHljX9OSP0jRC5TRNVA4qRc839t4g8KQaR8t0Uv0EFVL0MlyG7m/ofjEgAROtYsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-modules": "1.0.0" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-info": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", - "integrity": "sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bluebird": "^3.1.1", - "debug": "^2.2.0", - "lodash.get": "^4.0.0", - "read-pkg-up": "^2.0.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/get-package-info/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" - } - }, - "node_modules/get-package-info/node_modules/ms": { - "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/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", - "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.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", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "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/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-3.0.0.tgz", - "integrity": "sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-path-inside": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", - "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "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 - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/junk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", - "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/listr2/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/meow": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/meow/-/meow-10.1.5.tgz", - "integrity": "sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.2", - "camelcase-keys": "^7.0.0", - "decamelize": "^5.0.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.2", - "read-pkg-up": "^8.0.0", - "redent": "^4.0.0", - "trim-newlines": "^4.0.2", - "type-fest": "^1.2.2", - "yargs-parser": "^20.2.9" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", - "integrity": "sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^3.0.2", - "parse-json": "^5.2.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-8.0.0.tgz", - "integrity": "sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^5.0.0", - "read-pkg": "^6.0.0", - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "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" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.71.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", - "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-api-version": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", - "integrity": "sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/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/noms": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", - "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", - "dev": true, - "license": "ISC", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "~1.0.31" - } - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-author": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", - "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "author-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ping": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/ping/-/ping-0.4.4.tgz", - "integrity": "sha512-56ZMC0j7SCsMMLdOoUg12VZCfj/+ZO+yfOSjaNCRrmZZr6GLbN2X/Ui56T15dI8NhiHckaw5X2pvyfAomanwqQ==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/postject": { - "version": "1.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", - "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "commander": "^9.4.0" - }, - "bin": { - "postject": "dist/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/postject/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/process-nextick-args": { - "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": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rcedit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-3.1.0.tgz", - "integrity": "sha512-WRlRdY1qZbu1L11DklT07KuHfRk42l0NFFJdaExELEu4fEQ982bP5Z6OWGPj/wLLIuKRQDCxZJGAwoFsxhZhNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn-windows-exe": "^1.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/read-binary-file-arch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "bin": { - "read-binary-file-arch": "cli.js" - } - }, - "node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/redent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", - "integrity": "sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^5.0.0", - "strip-indent": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-package": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-package/-/resolve-package-1.0.1.tgz", - "integrity": "sha512-rzB7NnQpOkPHBWFPP3prUMqOP6yg3HkRGgcvR+lDyvyHoY3fZLFLYDkPXh78SPVBAE6VTCk/V+j8we4djg6o4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-installed-path": "^2.0.3" - }, - "engines": { - "node": ">=4", - "npm": ">=2" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", - "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-outer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/sudo-prompt": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", - "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/temp": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/isarray": { - "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/through2/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", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "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/through2/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" - } - }, - "node_modules/tiny-each-async": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", - "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/trim-newlines": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-4.1.1.tgz", - "integrity": "sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/trim-repeated/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/username": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/username/-/username-5.1.0.tgz", - "integrity": "sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^1.0.0", - "mem": "^4.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/util-deprecate": { - "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/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yarn-or-npm": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/yarn-or-npm/-/yarn-or-npm-3.0.1.tgz", - "integrity": "sha512-fTiQP6WbDAh5QZAVdbMQkecZoahnbOjClTQhzv74WX5h2Uaidj1isf9FDes11TKtsZ0/ZVfZsqZ+O3x6aLERHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.5", - "pkg-dir": "^4.2.0" - }, - "bin": { - "yarn-or-npm": "bin/index.js", - "yon": "bin/index.js" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/yarn-or-npm/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/yarn-or-npm/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/yarn-or-npm/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/yarn-or-npm/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-or-npm/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/yarn-or-npm/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/CEO/package.json b/CEO/package.json deleted file mode 100644 index cfcf5fe..0000000 --- a/CEO/package.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "name": "ceoapp", - "productName": "CeoApp", - "version": "1.0.0", - "description": "Aplicatie P2P pentru stocarea resurselor digitale", - "scripts": { - "clean": "del-cli dist && del-cli out", - "build-dist": "tsc && copyfiles -u 1 'src/**/*' dist", - "start-dev": "tsc && copyfiles -u 1 'src/**/*' dist && electron dist/main/main.js", - "start": "npm run clean && npm run build-dist && electron-forge start", - "package": "npm run clean && npm run build-dist && electron-forge package", - "make": "npm run clean && npm run build-dist && electron-forge make" - }, - "main": "dist/main/main.js", - "author": "Cerbu Andrei - Mihnea", - "license": "ISC", - "dependencies": { - "dotenv": "^16.4.5", - "ping": "^0.4.4", - "proper-lockfile": "^4.1.2", - "uuid": "^10.0.0" - }, - "devDependencies": { - "@electron-forge/cli": "^6.0.0", - "@electron-forge/maker-deb": "^6.0.0", - "@electron-forge/maker-rpm": "^6.0.0", - "@electron-forge/maker-squirrel": "^6.0.0", - "@electron-forge/maker-zip": "^6.0.0", - "@types/ping": "^0.4.4", - "@types/proper-lockfile": "^4.1.4", - "@types/uuid": "^10.0.0", - "check-disk-space": "^3.4.0", - "copyfiles": "^2.4.1", - "del-cli": "^5.0.0", - "electron": "^33.0.2", - "typescript": "^5.6.2" - }, - "config": { - "forge": { - "packagerConfig": { - "executableName": "ceoapp", - "name": "CeoApp", - "icon": "../app_icons/icon.ico", - "ignore": [ - "src", - ".idea", - "tsconfig.json" - ] - }, - "makers": [ - { - "name": "@electron-forge/maker-squirrel", - "config": { - "name": "CEOApp", - "setupIcon": "../app_icons/icon.ico" - } - }, - { - "name": "@electron-forge/maker-zip", - "platforms": [ - "darwin" - ], - "config": { - "icon": "../app_icons/icon.icns" - } - }, - { - "name": "@electron-forge/maker-deb", - "platforms": [ - "linux" - ], - "config": { - "icon": "../app_icons/icon.png" - } - } - ] - } - } -} diff --git a/CEO/render/js/reset_database.js b/CEO/render/js/reset_database.js deleted file mode 100644 index d640c5a..0000000 --- a/CEO/render/js/reset_database.js +++ /dev/null @@ -1,31 +0,0 @@ -document.addEventListener('DOMContentLoaded', async function () { - const operationCodes = await window.electronAPI.getOperationsCodes(); - if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); - return; - } - - const codeResetDatabase = operationCodes.RESET_DATABASE; - const codeOk = operationCodes.OK; - - // Open a TCP socket to the stored IP - if (!await window.electronAPI.openUcSocket()) { - await window.electronAPI.showAlert('Internal error of the application. Unable to open socket.'); - return; - } - - if (!await window.electronAPI.sendUcMessage(codeResetDatabase)) { - await window.electronAPI.showAlert('Failed to send login request.'); - return; - } - - const response = await waitForResponse(); - if (response && response.operationCode !== codeOk) { - await window.electronAPI.showAlert('Database reset failed.'); - return; - } - - await window.electronAPI.closeUcSocket(); - await new Promise(resolve => setTimeout(resolve, 2000)); - fadeOut('login'); -}); \ No newline at end of file diff --git a/CEO/src/helpers/announcement_sender.ts b/CEO/src/helpers/announcement_sender.ts deleted file mode 100644 index c23640d..0000000 --- a/CEO/src/helpers/announcement_sender.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { JsonManager } from './json_manager'; // Assuming this manages JSON configurations -import { TcpCommunicator } from "./tcp_communicator"; -import { operationCodes } from '../network/operation_codes'; // Assuming this holds operation codes -import { parentPort } from 'worker_threads'; -import { ParsedMessage } from "../network/message_handler"; - -export class AnnouncementSender { - private applicationInfo: JsonManager; - private readonly clientPort: number; - private message: string = ''; - private tcpCommunicator: TcpCommunicator | null = null; - private stopRequested: boolean = false; - - constructor(applicationInfoPath: string, clientPort: number) { - this.applicationInfo = new JsonManager(applicationInfoPath); - this.clientPort = clientPort; - } - - async start(message: string): Promise { - console.log('AnnouncementWorker started.'); - this.message = message; - this.stopRequested = false; - - try { - const activeUsersIp = await this.applicationInfo.readValue('users_ip'); - if (!activeUsersIp || !activeUsersIp.length) { - throw new Error('No active users found.'); - } - - for (const ip of activeUsersIp) { - if (this.stopRequested) { - console.log('AnnouncementWorker stopped.'); - break; - } - - const success = await this.sendAnnouncementToIp(ip); - if (!success) { - throw new Error(`Failed to send announcement to all users.`); - } - console.log(`Announcement sent and confirmed successfully from ${ip}`); - } - - process.send?.({ type: 'showAlert', message: 'Announcement sent to all active users successfully.' }); - } catch (error: any) { - console.error('Error in AnnouncementWorker:', error); - process.send?.({ type: 'shotAlert', message: `A problem occurred: ${error.message}` }); - } - - console.log('AnnouncementWorker finished.'); - } - - async stop(): Promise { - console.log('Stopping AnnouncementWorker...'); - this.stopRequested = true; - if (this.tcpCommunicator) { - await this.tcpCommunicator.disconnect(); - } - console.log('AnnouncementWorker stopped.'); - } - - private async sendAnnouncementToIp(ip: string): Promise { - this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort); - if (!await this.tcpCommunicator.connect()) { - console.log(`Skipping user at IP ${ip} - unable to connect.`); - return true; - } - - // Prepare the message metadata - const metaInfo = { message: this.message }; - - // Send the announcement message - const messageSent = await this.tcpCommunicator.sendMessage(operationCodes.SEND_ANNOUNCEMENT, metaInfo); - if (!messageSent) { - await this.tcpCommunicator.disconnect(); - return false; - } - - // Await confirmation from the user - const response = await this.waitForResponse(); - if (response?.operationCode === operationCodes.OK) { - await this.tcpCommunicator.disconnect(); - return true; - } - - // If confirmation is not OK, disconnect and halt - await this.tcpCommunicator.disconnect(); - return false; - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (this.stopRequested || !this.tcpCommunicator) { - clearInterval(idResponseCheck); - resolve(null); - return; - } - - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(this.tcpCommunicator.getLastResult()); - } - }, 100); - }); - } -} diff --git a/CEO/src/helpers/backup_manager.ts b/CEO/src/helpers/backup_manager.ts deleted file mode 100644 index ae87b65..0000000 --- a/CEO/src/helpers/backup_manager.ts +++ /dev/null @@ -1,192 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { FileEncryptor } from './file_encryptor'; -import { MemoryManager } from './memory_manager'; -import { JsonManager } from './json_manager'; -import { TcpCommunicator } from './tcp_communicator'; -import { operationCodes } from '../network/operation_codes'; -import { ParsedMessage } from "../network/message_handler"; - -export class BackupManager { - private fileEncryptor: FileEncryptor | null = null; - private memoryManager: MemoryManager; - private applicationInfo: JsonManager; - private userConfig: JsonManager; - private readonly clientPort: number; - private isBusy: boolean = false; - private intervalId: NodeJS.Timeout | null = null; - private stopRequested: boolean = false; - - constructor(userConfigPath: string, applicationInfoPath: string, memoryManagerPath: string, clientPort: number) { - this.applicationInfo = new JsonManager(applicationInfoPath); - this.userConfig = new JsonManager(userConfigPath); - this.memoryManager = new MemoryManager(memoryManagerPath); - this.clientPort = clientPort; - } - - async start(): Promise { - this.intervalId = setInterval(async () => { - if (!this.isBusy || !this.stopRequested) { - this.isBusy = true; - this.log('Start successfully. Backup files to users.'); - await this.initialize(); - } - - if (global.gc) { - global.gc(); - } - }, 10000); // 10-second interval for testing - } - - private async initialize(): Promise { - this.isBusy = true; - try { - const encryptionKeyData = await this.userConfig.readValue('encryption_key'); - if (!encryptionKeyData || !encryptionKeyData.key || !encryptionKeyData.iv) { - this.log('Encryption key data is missing in user configuration.', 'error'); - return; - } - - this.fileEncryptor = new FileEncryptor(encryptionKeyData.key, encryptionKeyData.iv); - - const userInfo = await this.userConfig.readValue('user_info'); - if (!userInfo || !userInfo.name) { - this.log('User information is missing in user configuration.', 'error'); - return; - } - const userName = userInfo.name; - - const backupDirectoryData = await this.applicationInfo.readValue('backupDirectory'); - if (!backupDirectoryData || !backupDirectoryData.id || !backupDirectoryData.path) { - this.log('Backup directory information is missing in application info.', 'error'); - return; - } - - const activeUsersIp = await this.applicationInfo.readValue('users_ip'); - if (!activeUsersIp || !activeUsersIp.length) { - this.log('No active users found.', 'error'); - return; - } - - const backupDirectoryId = backupDirectoryData.id; - const backupDirectoryPath = backupDirectoryData.path; - - const directoryData = await this.memoryManager.retrieveMetaInformation(backupDirectoryId); - if (!directoryData || !directoryData.structure) { - this.log('Backup directory structure is missing in memory.', 'error'); - return; - } - - await this.sendFilesToUsers(directoryData.structure, userName, activeUsersIp, backupDirectoryPath); - } catch (error: any) { - this.log(`Error in initialize process: ${error.message}`, 'error'); - } finally { - this.log('Backup process completed.'); - this.isBusy = false; - } - } - - private encryptFile(filePath: string): string { - if (!this.fileEncryptor) { - return filePath; - } - - if (!fs.existsSync(filePath)) { - this.log(`File not found: ${filePath}`, 'error'); - return ''; - } - - return this.fileEncryptor.encryptFileToBase64(filePath); - } - - private async sendFilesToUsers(fileStructure: { [key: string]: string }, userName: string, usersIp: string[], backupDirectoryPath: string): Promise { - let unsentFiles = Object.keys(fileStructure); - - for (const fileName of unsentFiles) { - const filePath = fileStructure[fileName]; - const encryptedFileContent = this.encryptFile(filePath); - - if (!encryptedFileContent) { - this.log(`Failed to encrypt file: ${fileName}`, 'error'); - continue; - } - - const relativeFilePath = path.relative(backupDirectoryPath, filePath); - const metaInfo = { userName, relativeFilePath }; - - for (const ip of usersIp) { - const tcpCommunicator = new TcpCommunicator(ip, this.clientPort); - - try { - await tcpCommunicator.connect(); - this.log(`Connected to ${ip}`); - - const sendSuccess = await tcpCommunicator.sendMessage(operationCodes.BACKUP_FILE, metaInfo, Buffer.from(encryptedFileContent, 'base64')); - if (!sendSuccess) { - throw new Error('Failed to send file content.'); - } - - const responseReceived = await this.waitForResponse(tcpCommunicator); - if (!responseReceived) { - throw new Error('Timeout waiting for the message response.'); - } - - this.log(`Successfully sent file: ${fileName} to ${ip}`); - unsentFiles = unsentFiles.filter(f => f !== fileName); - break; - } catch (error) { - this.log(`Failed to send file: ${fileName} to ${ip}. Error: ${error}`, 'error'); - } finally { - await tcpCommunicator.disconnect(); - this.log(`Disconnected from ${ip}`); - } - } - } - - if (unsentFiles.length > 0) { - process.send?.({type: 'log', message: 'Backup could not be completed for all files'}); - } else { - process.send?.({type: 'log', message: 'Backup completed successfully' }); - } - } - - private async waitForResponse(tcpCommunicator: TcpCommunicator): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(() => { - if (!tcpCommunicator) return null; - if (tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(tcpCommunicator.getLastResult()); - } - }, 100); - }); - } - - async stop(): Promise { - this.stopRequested = true; // Signal that stop is requested - - if (this.intervalId) { - clearInterval(this.intervalId); - this.intervalId = null; - } - - // Wait for any ongoing process to complete if busy - while (this.isBusy) { - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - console.log("[BackupManager] Stopped successfully."); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' | 'warn' = 'log'): void { - const prefix = '[BackupManager]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else if (level === 'warn') { - console.warn(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } -} diff --git a/CEO/src/helpers/backup_retrieval.ts b/CEO/src/helpers/backup_retrieval.ts deleted file mode 100644 index aec9696..0000000 --- a/CEO/src/helpers/backup_retrieval.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { JsonManager } from './json_manager'; -import { TcpCommunicator } from "./tcp_communicator"; -import { operationCodes } from '../network/operation_codes'; -import path from 'path'; -import fs from 'fs'; -import crypto from 'crypto'; -import { ParsedMessage } from "../network/message_handler"; - -export class BackupRetrievalWorker { - private userConfig: JsonManager; - private applicationInfo: JsonManager; - private readonly clientPort: number; - private readonly destinationPath: string; - private encryptionKey: Buffer | null = null; - private iv: Buffer | null = null; - private tcpCommunicator: TcpCommunicator | null = null; - private stopRequested: boolean = false; - private isBusy: boolean = false; - - constructor(userConfigPath: string, applicationInfoPath: string, clientPort: number, destinationPath: string) { - this.userConfig = new JsonManager(userConfigPath); - this.applicationInfo = new JsonManager(applicationInfoPath); - this.clientPort = clientPort; - this.destinationPath = destinationPath; - } - - // Logging helper function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[BackupRetrievalWorker]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - async start(): Promise { - if(!this.stopRequested) return; - this.isBusy = true; - try { - const userInfo = await this.userConfig.readValue('user_info'); - if (!userInfo || !userInfo.name) { - throw new Error('User information or name is missing.'); - } - const userName = userInfo.name; - - const encryptionData = await this.userConfig.readValue('encryption_key'); - if (!encryptionData || !encryptionData.key || !encryptionData.iv) { - throw new Error('Encryption key or IV is missing.'); - } - - this.encryptionKey = Buffer.from(encryptionData.key, 'base64'); - this.iv = Buffer.from(encryptionData.iv, 'base64'); - - const activeUsersIp = await this.applicationInfo.readValue('users_ip'); - if (!activeUsersIp || !activeUsersIp.length) { - throw new Error('No active users found.'); - } - - for (const ip of activeUsersIp) { - const success = await this.processBackupForIp(ip, userName); - if (!success) { - throw new Error(`Failed to retrieve backup from ${ip}`); - } - this.log(`Backup retrieved successfully from ${ip}`); - } - - process.send?.({ type: 'showAlert', message: 'Backup retrieval completed successfully.' }); - process.send?.({ type: 'changeContent', page: 'main_menu' }); - } catch (error: any) { - this.log(`Error in BackupRetrievalWorker: ${error.message}`, 'error'); - process.send?.({ type: 'showAlert', message: `A problem occurred: ${error.message}` }); - process.send?.({ type: 'changeContent', page: 'main_menu' }); - } - finally { - this.isBusy = false; - } - - if (global.gc) { - global.gc(); - } - } - - private async processBackupForIp(ip: string, userName: string): Promise { - this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort); - if (!await this.tcpCommunicator.connect()) { - this.log(`Failed to connect to ${ip}`, 'error'); - return true; - } - - const backupExists = await this.checkIfBackupExists(userName); - if (!backupExists) { - this.log(`No backup found for user ${userName} on IP ${ip}`); - await this.tcpCommunicator.disconnect(); - return true; - } - - const backupStructure = await this.requestBackupStructure(userName); - if (!backupStructure || Object.keys(backupStructure).length === 0) { - this.log(`No files found in backup structure for user ${userName} on IP ${ip}`); - await this.tcpCommunicator.disconnect(); - return true; - } - - for (const relativeFilePath of Object.keys(backupStructure)) { - const fileRequestSuccess = await this.requestBackupFile(userName, relativeFilePath); - if (!fileRequestSuccess) { - await this.tcpCommunicator.disconnect(); - throw new Error(`Failed to retrieve file ${relativeFilePath} from backup for user ${userName} on IP ${ip}`); - } - } - - await this.tcpCommunicator.disconnect(); - return true; - } - - private async checkIfBackupExists(userName: string): Promise { - if (!this.tcpCommunicator) return false; - - const metaInfo = { name: userName }; - if (!await this.tcpCommunicator.sendMessage(operationCodes.IS_BACKUP_CREATED, metaInfo)) return false; - - const response = await this.waitForResponse(); - return response?.metaInfo?.backupExists === true; - } - - private async requestBackupStructure(userName: string): Promise { - if (!this.tcpCommunicator) return false; - - const metaInfo = { name: userName }; - if (!await this.tcpCommunicator.sendMessage(operationCodes.GET_BACKUP_STRUCTURE, metaInfo)) return null; - - const response = await this.waitForResponse(); - return response?.metaInfo?.structure || null; - } - - private async requestBackupFile(userName: string, relativeFilePath: string): Promise { - if (!this.tcpCommunicator) return false; - - const metaInfo = { name: userName, relativeFilePath }; - if (!await this.tcpCommunicator.sendMessage(operationCodes.REQ_FILE_FROM_BACKUP, metaInfo)) return false; - - const response = await this.waitForResponse(); - if (response?.operationCode === operationCodes.OK && response.metaInfo && response.fileContent) { - return this.saveFile(response.metaInfo.relativeFilePath, response.fileContent.toString('base64')); - } - return false; - } - - private saveFile(relativeFilePath: string, fileContent: string): boolean { - if (!this.encryptionKey || !this.iv) { - throw new Error('Encryption key or IV is not set.'); - } - - let encryptedBuffer: Buffer; - try { - encryptedBuffer = Buffer.from(fileContent, 'base64'); - } catch (error: any) { - throw new Error(`Error decoding base64 file content: ${error.message}`); - } - - let decryptedContent: Buffer; - try { - const decipher = crypto.createDecipheriv('aes-256-cbc', this.encryptionKey, this.iv); - decryptedContent = Buffer.concat([decipher.update(encryptedBuffer), decipher.final()]); - } catch (error: any) { - throw new Error(`Error decrypting file: ${error.message}`); - } - - const fullFilePath = path.join(this.destinationPath, relativeFilePath); - try { - const dirPath = path.dirname(fullFilePath); - if (!fs.existsSync(dirPath)) { - fs.mkdirSync(dirPath, { recursive: true }); - } - fs.writeFileSync(fullFilePath, decryptedContent); - this.log(`File saved successfully: ${fullFilePath}`); - return true; - } catch (error: any) { - throw new Error(`Error saving file ${relativeFilePath}: ${error.message}`); - } - } - - async stop(): Promise { - this.stopRequested = true; // Signal that stop is requested - - // Wait for any ongoing process to complete if busy - while (this.isBusy) { - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - console.log("[BackupManager] Stopped successfully."); - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (!this.tcpCommunicator) return null; - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(this.tcpCommunicator.getLastResult()); - } - }, 100); - }); - } -} diff --git a/CEO/src/helpers/department_sharer.ts b/CEO/src/helpers/department_sharer.ts deleted file mode 100644 index ea844b7..0000000 --- a/CEO/src/helpers/department_sharer.ts +++ /dev/null @@ -1,214 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { TcpCommunicator } from './tcp_communicator'; -import { operationCodes } from '../network/operation_codes'; -import { JsonManager } from './json_manager'; -import { MemoryManager } from './memory_manager'; -import { ParsedMessage } from "../network/message_handler"; - -export class DepartmentSharer { - private userConfig: JsonManager; - private applicationInfo: JsonManager; - private memoryManager: MemoryManager; - private departmentDirectory: string | null; - private readonly clientPort: number; - private isBusy: boolean = false; - private tcpCommunicator: TcpCommunicator | null = null; - private stopRequested: boolean = false; - private intervalId: NodeJS.Timeout | null = null; - - constructor( - userConfigPath: string, - applicationInfoPath: string, - memoryManagerPath: string, - clientPort: number - ) { - this.userConfig = new JsonManager(userConfigPath); - this.applicationInfo = new JsonManager(applicationInfoPath); - this.memoryManager = new MemoryManager(memoryManagerPath); - this.clientPort = clientPort; - this.departmentDirectory = null; - } - - // Start sharing files with the department every minute - async start(): Promise { - this.intervalId = setInterval(async () => { - if (!this.isBusy || !this.stopRequested) { - this.isBusy = true; - this.log('Start successfully. Sharing files with the department.'); - await this.shareFilesWithDepartment(); - } - - if (global.gc) { - global.gc(); - } - }, 10000); // 10-second interval for testing - } - - // Share files with users in the same department - private async shareFilesWithDepartment(): Promise { - try { - // Get the current user's department information - const userInfo = await this.userConfig.readValue('user_info'); - if (!userInfo || !userInfo.departmentId || !userInfo.name) { - throw new Error('User information or department ID is missing in the configuration.'); - } - - const departmentId = userInfo.departmentId; - const userName = userInfo.name; - - // Get the list of active users from applicationInfo - const activeUsersId = await this.applicationInfo.readValue('active_users_info'); - if (!activeUsersId) { - throw new Error('No active users found.'); - } - - const activeUsers = await this.memoryManager.retrieveMetaInformation(activeUsersId); - if (!activeUsers || activeUsers.length === 0) { - throw new Error('No active users found.'); - } - - // Filter users who belong to the same department - const departmentUsers = activeUsers.filter((user: any) => user.user_info.departmentId === departmentId); - if (departmentUsers.length === 0) { - throw new Error('No users found in the same department.'); - } - - // Get department directory info - const departmentData = await this.applicationInfo.readValue('departmentDirectory'); - if (!departmentData || !departmentData.path || !departmentData.id) { - throw new Error('No department directory found.'); - } - - this.departmentDirectory = departmentData.path; - - // Read files from the MemoryManager related to this department - const departmentFiles = await this.memoryManager.retrieveMetaInformation(departmentData.id); - if (!departmentFiles || !departmentFiles.structure) { - throw new Error('No files found for this department in the memory manager.'); - } - - // Iterate over all department users and perform the operations - for (const user of departmentUsers) { - const userIp = user.ip; - this.tcpCommunicator = new TcpCommunicator(userIp, this.clientPort); - - if (!await this.tcpCommunicator.connect()) continue; - - // First clear the department directory; - if (await this.clearDepartmentDirectory(userName)) { - await this.sendFilesToUser(departmentFiles.structure, userName); - } - - await this.tcpCommunicator.disconnect(); - } - } - catch(error: any) { - this.log(error.message, 'error'); - } - finally{ - this.log('Department sharing completed.'); - this.isBusy = false; - } - } - - // Clear the department directory for a user - private async clearDepartmentDirectory(userName: string): Promise { - if(!this.tcpCommunicator) return false; - - if (!await this.tcpCommunicator.sendMessage(operationCodes.CLEAR_DEPARTMENT, {userName: userName})) return false; - const response = await this.waitForResponse(); - - if (!response || response.operationCode !== operationCodes.OK){ - this.log('Failed to clear the department directory.', 'error'); - return false; - } - - return true; - } - - // Send the files to a user in the department - private async sendFilesToUser(files: { [key: string]: string }, userName: string): Promise { - if(!this.tcpCommunicator) return; - const unsentFiles = Object.keys(files); - - console.log(`\n\n${unsentFiles}\n\n`); - - for (const fileName of unsentFiles) { - const filePath = files[fileName]; - - // Ensure the file exists before attempting to send - if (!fs.existsSync(filePath)) { - this.log(`File not found: ${filePath}`, 'error'); - continue; - } - - // Read the file content - const fileContent = fs.readFileSync(filePath); - - // Get the relative path of the file (used in the meta info) - if (!this.departmentDirectory) return; - const relativeFilePath = path.relative(this.departmentDirectory, filePath); - - // Prepare the metaInfo (same structure as FileSharer) - const metaInfo = { - userName, - relativeFilePath - }; - - // Send the file - if (!await this.tcpCommunicator.sendMessage(operationCodes.DEPARTMENT_FILE, metaInfo, Buffer.from(fileContent))) return; - - console.log(`\n\nSending file: ${fileName} to ${userName}\n\n`); - - const response = await this.waitForResponse(); - if (!response || response.operationCode !== operationCodes.OK) { - this.log(`Failed to send file: ${fileName}`, 'error'); - return; - } - - this.log(`File sent successfully: ${fileName} to ${userName}`); - - unsentFiles.splice(unsentFiles.indexOf(fileName), 1); - await this.tcpCommunicator.disconnect(); - } - } - - async stop(): Promise { - this.stopRequested = true; // Signal that stop is requested - - if (this.intervalId) { - clearInterval(this.intervalId); - this.intervalId = null; - } - - // Wait for any ongoing process to complete if busy - while (this.isBusy) { - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - console.log("[BackupManager] Stopped successfully."); - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (!this.tcpCommunicator) return null; - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(this.tcpCommunicator.getLastResult()); - } - }, 100); - }); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[DepartmentSharer]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } -} diff --git a/CEO/src/helpers/directory_watcher.ts b/CEO/src/helpers/directory_watcher.ts deleted file mode 100644 index 7549485..0000000 --- a/CEO/src/helpers/directory_watcher.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { promises as fs, watch, FSWatcher } from 'fs'; -import path from 'path'; -import { MemoryManager } from './memory_manager'; -import { JsonManager } from './json_manager'; - -export class DirectoryWatcher { - private directoryPath: string; - private directoryMemoryId: string; - private directoryScheme: any; - private applicationInfo: JsonManager; - private memoryManager: MemoryManager; - private readonly sourceKey: string; - private directoryWatcher: FSWatcher | null; - private totalSize: number; - private isBusy: boolean; - - constructor(memoryManagerPath: string, applicationInfoPath: string, sourceKey: string) { - this.sourceKey = sourceKey; - this.applicationInfo = new JsonManager(applicationInfoPath); - this.memoryManager = new MemoryManager(memoryManagerPath); - this.directoryMemoryId = ''; - this.directoryPath = ''; - this.directoryWatcher = null; - this.totalSize = 0; - this.isBusy = false; - } - - // Start the watcher with a busy flag to prevent overlapping operations - async start(): Promise { - setInterval(async () => { - if (!this.isBusy) { - this.isBusy = true; - const initialized = await this.initialize(); - if (initialized) this.log('Directory watcher started successfully.'); - this.isBusy = false; - } - }, 10000); // 10-second interval for testing - } - - // Method to initialize and validate the backup directory - async initialize(): Promise { - const directoryData = await this.applicationInfo.readValue(this.sourceKey); - if (!directoryData) { - this.log('Directory data not found in application info.', 'error'); - return false; - } - - this.directoryPath = directoryData.path; - this.directoryMemoryId = directoryData.id; - - if (!this.directoryMemoryId || !this.directoryPath) { - this.log('Components of entry in \'DirectoryWatcher\' not found.', 'error'); - await this.applicationInfo.removeValue(this.sourceKey); - return false; - } - - if (!this.directoryScheme || Object.keys(this.directoryScheme).length === 0) { - // No structure in memory, scan and save it - const result = await this.buildDirectoryScheme(this.directoryPath); - this.directoryScheme = result.structure; - this.totalSize = result.size; - - await this.memoryManager.updateMetaInformation(this.directoryMemoryId, { - structure: this.directoryScheme, - totalSize: this.totalSize, - }); - } - - // Start watching the directory (after stopping any existing watcher) - this.restartWatcher(); - return true; - } - - // Recursively build the directory structure and calculate the total size - private async buildDirectoryScheme(dirPath: string): Promise<{ structure: any, size: number }> { - const directoryScheme: any = {}; - let totalSize = 0; - - const items = await fs.readdir(dirPath, { withFileTypes: true }); - - for (const item of items) { - const fullPath = path.join(dirPath, item.name); - const stats = await fs.stat(fullPath); - - if (item.isDirectory()) { - // If it's a directory, recursively build its structure and accumulate size - const { structure, size } = await this.buildDirectoryScheme(fullPath); - directoryScheme[item.name] = structure; - totalSize += size; - } else if (item.isFile()) { - // If it's a file, store its full path and accumulate size - directoryScheme[item.name] = fullPath; - totalSize += stats.size; - } - } - - return { structure: directoryScheme, size: totalSize }; - } - - // Restart the directory watcher, ensuring any previous watcher is closed - private restartWatcher(): void { - if (this.directoryWatcher) { - this.log('Stopping existing watcher...'); - this.directoryWatcher.close(); - } - - this.startDirectoryWatcher(); - } - - // Start watching the backup directory for changes - private startDirectoryWatcher(): void { - if (!this.directoryPath) { - throw new Error('Backup directory not set. Cannot start watcher.'); - } - - this.directoryWatcher = watch(this.directoryPath, { recursive: true }, async (eventType, filename) => { - if (filename) { - this.log(`File change detected: ${eventType} - ${filename}`); - // Rebuild the directory scheme and update memory - const result = await this.buildDirectoryScheme(this.directoryPath); - this.directoryScheme = result.structure; - this.totalSize = result.size; - - await this.memoryManager.updateMetaInformation(this.directoryMemoryId, { - structure: this.directoryScheme, - totalSize: this.totalSize, - }); - - this.log('Directory structure and size updated in memory.'); - } - }); - - this.log(`Watching for changes in: ${this.directoryPath}`); - } - - // Close the directory watcher - public closeWatcher(): void { - if (this.directoryWatcher) { - this.log(`Stopping watcher for ${this.directoryPath}`); - this.directoryWatcher.close(); - this.directoryWatcher = null; - } - - if (global.gc) { - global.gc(); - } - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const sourcePrefix = `[DirectoryWatcher] {${this.capitalize(this.sourceKey)}}`; - if (level === 'error') { - console.error(`${sourcePrefix} ${message}`); - } else { - console.log(`${sourcePrefix} ${message}`); - } - } - - // Capitalize the first letter of the sourceKey - private capitalize(str: string): string { - return str.charAt(0).toUpperCase() + str.slice(1); - } -} diff --git a/CEO/src/helpers/file_encryptor.ts b/CEO/src/helpers/file_encryptor.ts deleted file mode 100644 index 20bc391..0000000 --- a/CEO/src/helpers/file_encryptor.ts +++ /dev/null @@ -1,55 +0,0 @@ -import fs from 'fs'; -import crypto from 'crypto'; - -export class FileEncryptor { - private readonly encryptionKey: Buffer; - private readonly iv: Buffer; - - constructor(base64Key: string, base64Iv: string) { - // Decode the base64-encoded key and IV - this.encryptionKey = Buffer.from(base64Key, 'base64'); - this.iv = Buffer.from(base64Iv, 'base64'); - } - - // Method to read a file, encrypt it, and return the encrypted content as a base64 string - public encryptFileToBase64(filePath: string): string { - try { - // Read the file contents - const fileBuffer = fs.readFileSync(filePath); - - // Create the cipher using AES-256-CBC (or another algorithm you prefer) - const cipher = crypto.createCipheriv('aes-256-cbc', this.encryptionKey, this.iv); - - // Encrypt the file data - let encryptedData = cipher.update(fileBuffer); - encryptedData = Buffer.concat([encryptedData, cipher.final()]); - - // Return the encrypted data as a base64 string - return encryptedData.toString('base64'); - } catch (err) { - console.error(`Error encrypting file at path ${filePath}:`, err); - throw err; - } - } - - // Method to decrypt base64-encoded encrypted content and return the decrypted buffer - public decryptBase64(encryptedBase64: string): Buffer { - try { - // Decode the base64-encoded encrypted data - const encryptedData = Buffer.from(encryptedBase64, 'base64'); - - // Create the decipher using AES-256-CBC - const decipher = crypto.createDecipheriv('aes-256-cbc', this.encryptionKey, this.iv); - - // Decrypt the data - let decryptedData = decipher.update(encryptedData); - decryptedData = Buffer.concat([decryptedData, decipher.final()]); - - // Return the decrypted buffer - return decryptedData; - } catch (err) { - console.error('Error decrypting data:', err); - throw err; - } - } -} diff --git a/CEO/src/helpers/file_sharer.ts b/CEO/src/helpers/file_sharer.ts deleted file mode 100644 index cada88f..0000000 --- a/CEO/src/helpers/file_sharer.ts +++ /dev/null @@ -1,146 +0,0 @@ -import fs from "fs"; -import path from "path"; -import { QueueManager } from './queue_manager'; -import { TcpCommunicator } from "./tcp_communicator"; -import { operationCodes } from '../network/operation_codes'; -import { compareFnFileItemTask, FileItemTask } from "../interfaces/file_item_task"; -import { ParsedMessage } from "../network/message_handler"; - -interface FileSendTask { - ip: string; - path: string; - userName: string; -} - -export class FileSharer { - private queueManager: QueueManager; - private readonly clientPort: number; - private isBusy: boolean; - private tcpCommunicator: TcpCommunicator | null = null; - private stopRequested: boolean = false; - private intervalId: NodeJS.Timeout | null = null; - - constructor(queueFilePath: string, clientPort: number) { - this.queueManager = new QueueManager(queueFilePath, compareFnFileItemTask); - this.clientPort = clientPort; - this.isBusy = false; // Initialize the busy flag - } - - // Start processing the file queue - async start(): Promise { - this.intervalId = setInterval(async () => { - if (!this.isBusy || !this.stopRequested) { // Check if the queue is already being processed - this.isBusy = true; // Set busy flag to true before starting - this.log("Start successfully. Processing the queue."); - await this.processQueue(); - } - - if (global.gc) { - global.gc(); - } - }, 10000); // 10 seconds interval - } - - // Method to process the queue - private async processQueue(): Promise { - while (!this.queueManager.isEmpty()) { - const task = this.queueManager.peek(); - this.log('trimiti fisier'); - - if (task) { - this.log(`Processing task for file: ${task.path} to IP: ${task.ip}`); - const success = await this.sendFile(task); - - if (!success) { - this.log(`Failed to send file: ${task.path} to IP: ${task.ip}. Re-adding to queue.`, 'error'); - this.queueManager.dequeue(); - this.queueManager.enqueue(task); // Re-add to queue if failed - } else { - this.log(`File sent successfully: ${task.path} to IP: ${task.ip}`); - this.queueManager.dequeue(); - } - } - } - this.isBusy = false; // Reset busy flag after the queue is processed - } - - // Method to send the file to a specific IP using TcpCommunicator - private async sendFile(task: FileSendTask): Promise { - const { ip, path: filePath, userName } = task; - - // Ensure the file exists before attempting to send - if (!fs.existsSync(filePath)) { - this.log(`File not found: ${filePath}`, 'error'); - return false; - } - - // Read the file contents - const fileContent = fs.readFileSync(filePath); - - // Extract the file name from the file path using path.basename - const fileName = path.basename(filePath); - - const metaInfo = { - userName, // Sender's username - relativeFilePath: fileName, // Use the file name instead of the full path - }; - - this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort); - - if (!await this.tcpCommunicator.connect()) { - this.log(`Failed to connect to IP: ${ip}`, 'error'); - return false; - } - - this.log(`Sending file: ${filePath} to IP: ${ip}`); - - if (!await this.tcpCommunicator.sendMessage(operationCodes.SHARE_FILE, metaInfo, fileContent)) return false; - - const response = await this.waitForResponse(); - if (!response || response.operationCode !== operationCodes.OK) { - this.log(`Failed to send file: ${filePath} to IP: ${ip}`, 'error'); - return false; - } - - await this.tcpCommunicator.disconnect(); - return true; - } - - async stop(): Promise { - this.stopRequested = true; // Signal that stop is requested - - if (this.intervalId) { - clearInterval(this.intervalId); - this.intervalId = null; - } - - // Wait for any ongoing process to complete if busy - while (this.isBusy) { - await new Promise((resolve) => setTimeout(resolve, 100)); - } - - console.log("[BackupManager] Stopped successfully."); - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (!this.tcpCommunicator) return null; - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(this.tcpCommunicator.getLastResult()); // Resolve the response or null if not available - } - }, 100); // Check every 100 milliseconds if the response has arrived - }); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[FileSharer]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } -} diff --git a/CEO/src/helpers/json_manager.ts b/CEO/src/helpers/json_manager.ts deleted file mode 100644 index 627acac..0000000 --- a/CEO/src/helpers/json_manager.ts +++ /dev/null @@ -1,119 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -export class JsonManager { - private readonly filePath: string; - private readonly lockFilePath: string; - - constructor(filePath: string) { - const dir = path.dirname(filePath); - - // Check if the directory exists, throw error if it doesn't - if (!fs.existsSync(dir)) { - throw new Error(`The directory does not exist: ${dir}`); - } - - this.filePath = filePath; - this.lockFilePath = `${filePath}.lock`; // Define the lock file path - - // If the file doesn't exist, create it - if (!fs.existsSync(filePath)) { - fs.writeFileSync(filePath, JSON.stringify({}, null, 2), 'utf8'); - } - } - - // Method to acquire a lock (create .lock file) - private async acquireLock(): Promise { - while (fs.existsSync(this.lockFilePath)) { - // Wait until the lock file is released - await new Promise(resolve => setTimeout(resolve, 100)); // 100ms delay before retrying - } - // Create the lock file - fs.writeFileSync(this.lockFilePath, ''); - } - - // Method to release the lock (delete .lock file) - private releaseLock(): void { - if (fs.existsSync(this.lockFilePath)) { - fs.unlinkSync(this.lockFilePath); - } - } - - // Read a value by key from the JSON file with a lock - public async readValue(key: string): Promise { - await this.acquireLock(); // Acquire the lock - - try { - if (!fs.existsSync(this.filePath)) return null; - - const data = JSON.parse(fs.readFileSync(this.filePath, 'utf8')); - return data[key] !== undefined ? data[key] : null; - } catch (err: any) { - console.error(`Error reading from JSON file: ${err.message}`); - return null; - } finally { - this.releaseLock(); // Always release the lock after the operation - } - } - - // Write a key-value pair to the JSON file with a lock - public async writeValue(key: string, value: any): Promise { - await this.acquireLock(); // Acquire the lock - - try { - let data: { [key: string]: any } = {}; - - if (fs.existsSync(this.filePath)) { - data = JSON.parse(fs.readFileSync(this.filePath, 'utf8')); - } - - // Update the key with the new value - data[key] = value; - - fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf8'); - return true; - } catch (err: any) { - console.error(`Error writing to JSON file: ${err.message}`); - return false; - } finally { - this.releaseLock(); // Always release the lock after the operation - } - } - - // Remove a key-value pair from the JSON file with a lock - public async removeValue(key: string): Promise { - await this.acquireLock(); // Acquire the lock - - try { - if (!fs.existsSync(this.filePath)) return false; - - const data = JSON.parse(fs.readFileSync(this.filePath, 'utf8')); - if (data[key] !== undefined) { - delete data[key]; - fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf8'); - return true; - } - return false; - } catch (err: any) { - console.error(`Error removing key from JSON file: ${err.message}`); - return false; - } finally { - this.releaseLock(); // Always release the lock after the operation - } - } - - // Reset the JSON file by clearing all data with a lock - public async resetFile(): Promise { - await this.acquireLock(); // Acquire the lock - - try { - fs.writeFileSync(this.filePath, JSON.stringify({}, null, 2), 'utf8'); - return true; - } catch (err: any) { - console.error(`Error resetting JSON file: ${err.message}`); - return false; - } finally { - this.releaseLock(); // Always release the lock after the operation - } - } -} diff --git a/CEO/src/helpers/memory_manager.ts b/CEO/src/helpers/memory_manager.ts deleted file mode 100644 index 93e93b2..0000000 --- a/CEO/src/helpers/memory_manager.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { v4 as uuidv4 } from 'uuid'; -import { JsonManager } from './json_manager'; - -export class MemoryManager extends JsonManager { - constructor(filePath: string) { - super(filePath); // Call the parent constructor to ensure file initialization - } - - // Generate a new unique GUID and ensure it doesn't already exist in the file - private generateUniqueGuid(): Promise { - const generate = async (): Promise => { - const guid = uuidv4(); - const value = await this.readValue(guid); - if (value === null) { - return guid; - } - return generate(); - }; - return generate(); - } - - // Store meta information with a unique GUID as the key - public async storeMetaInformation(metaInfo: any): Promise { - const guid = await this.generateUniqueGuid(); - const success = await this.writeValue(guid, metaInfo); - if (success) { - return guid; // Return the unique GUID for future reference - } else { - throw new Error('Failed to store meta information.'); - } - } - - // Retrieve meta information using the GUID - public retrieveMetaInformation(guid: string): Promise { - return this.readValue(guid); - } - - // Update meta information by merging new data into existing data - public async updateMetaInformation(guid: string, newMetaInfo: any): Promise { - return await this.writeValue(guid, newMetaInfo); - } - - // Remove meta information using the GUID - public removeMetaInformation(guid: string): Promise { - return this.removeValue(guid); - } -} diff --git a/CEO/src/helpers/network_scanner.ts b/CEO/src/helpers/network_scanner.ts deleted file mode 100644 index d1ce897..0000000 --- a/CEO/src/helpers/network_scanner.ts +++ /dev/null @@ -1,185 +0,0 @@ -import {JsonManager} from "./json_manager"; -import {UdpClient} from "../network/udp/udp_client"; -import {TcpCommunicator} from "./tcp_communicator"; -import {operationCodes} from "../network/operation_codes"; -import {ParsedMessage} from "../network/message_handler"; - -export class NetworkScanner { - private applicationInfo: JsonManager; - private userConfig: JsonManager; - private readonly udpPort: number; - private readonly tcpPort: number; - private readonly okPage: string; - private readonly errorPage: string; - private readonly databaseResetPage: string; - private appStarted = false; - private intervalIds: NodeJS.Timeout[] = []; - - // Flags to prevent overlapping executions - private ucCheckBusy = false; - private ipLookupBusy = false; - private sendLoginBusy = false; - - constructor(applicationInfoPath: string, userConfigPath: string, udpPort: number, tcpPort: number, okPage: string, errorPage: string, databaseResetPage: string) { - this.applicationInfo = new JsonManager(applicationInfoPath); - this.userConfig = new JsonManager(userConfigPath); - this.udpPort = udpPort; - this.tcpPort = tcpPort; - this.okPage = okPage; - this.errorPage = errorPage; - this.databaseResetPage = databaseResetPage; - - // Start tasks - this.startUCCheck(); - this.startUserIPLookup(); - this.sendLoginRequest(); - } - - // Log helper function for consistent logging format - private log(message: string, level: 'log' | 'error' = 'log', methodName: string = ''): void { - const prefix = `[NetworkScanner${methodName ? `.${methodName}` : ''}]`; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - // UC Check Task - private startUCCheck(interval: number = 5000): void { - const intervalId = setInterval(async () => { - if (this.ucCheckBusy) return; - this.ucCheckBusy = true; - - try { - this.log('UC Check running...', 'log', 'startUCCheck'); - const udpClient = new UdpClient(this.udpPort); - const aliveClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_UC); - const storedIp = await this.applicationInfo.readValue('serverIp'); - const foundClient = aliveClients.length > 0; - - if (foundClient) { - const ipAddress = aliveClients[0]; // Use the first alive client - - if (!storedIp || storedIp !== ipAddress) { - await this.applicationInfo.writeValue('serverIp', ipAddress); - if (!this.appStarted) { - process.send?.({ type: 'changeContent', page: this.okPage }); - } - this.appStarted = true; - } else if (!this.appStarted) { - process.send?.({ type: 'changeContent', page: this.okPage }); - this.appStarted = true; - } - } else { - process.send?.({ type: 'changeContent', page: this.errorPage }); - } - } catch (err) { - this.log(`Error checking UC: ${err}`, 'error', 'startUCCheck'); - process.send?.({ type: 'changeContent', page: this.errorPage }); - } finally { - this.ucCheckBusy = false; - } - }, interval); - - this.intervalIds.push(intervalId); - } - - // IP Lookup Task - private startUserIPLookup(interval: number = 10000): void { - const intervalId = setInterval(async () => { - if (this.ipLookupBusy) return; - this.ipLookupBusy = true; - - try { - this.log('IP Lookup running...', 'log', 'startUserIPLookup'); - const serverIp = await this.applicationInfo.readValue('serverIp'); - const udpClient = new UdpClient(this.udpPort); - const activeIPs = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN); - const filteredIPs = activeIPs.filter(ip => ip !== serverIp); - - // Save the filtered IPs to 'users_ip' - await this.applicationInfo.writeValue('users_ip', filteredIPs); - } catch (err) { - this.log(`Error during user IP lookup: ${err}`, 'error', 'startUserIPLookup'); - } finally { - this.ipLookupBusy = false; - } - }, interval); - - this.intervalIds.push(intervalId); - } - - // Login Request Task - private sendLoginRequest(interval: number = 5000): void { - const intervalId = setInterval(async () => { - if (this.sendLoginBusy || this.appStarted) return; - this.sendLoginBusy = true; - - try { - const userInfo = await this.userConfig.readValue('user_info'); - if (!userInfo || !userInfo.email || !userInfo.password) { - this.log("Email or password not found in user config.", 'error', 'sendLoginRequest'); - return; - } - - const app_type = await this.userConfig.readValue('app_type'); - const email = userInfo.email; - const password = userInfo.password; - const serverIp = await this.applicationInfo.readValue('serverIp'); - - if (!serverIp) { - this.log("Server IP not found in application info.", 'error', 'sendLoginRequest'); - return; - } - - const tcpCommunicator = new TcpCommunicator(serverIp, this.tcpPort); - - if (!await tcpCommunicator.connect()) { - this.log("Failed to connect to the server.", 'error', 'sendLoginRequest'); - return; - } - - const metaInfo = { email, password, app_type }; - if (!await tcpCommunicator.sendMessage(operationCodes.LOGIN, metaInfo)) { - this.log("Failed to send login request.", 'error', 'sendLoginRequest'); - await tcpCommunicator.disconnect(); - return; - } - - const response = await this.waitForResponse(tcpCommunicator); - if (response?.operationCode !== operationCodes.OK) { - await this.userConfig.resetFile(); - await this.userConfig.writeValue('app_type', app_type); - process.send?.({ type: 'changeContent', page: this.databaseResetPage }); - } - } catch (err) { - this.log(`Error during login request: ${err}`, 'error', 'sendLoginRequest'); - } finally { - this.sendLoginBusy = false; - } - }, interval); - - this.intervalIds.push(intervalId); - } - - // Helper function to wait for a response from the TCP communicator - private async waitForResponse(tcpCommunicator: TcpCommunicator): Promise { - return new Promise((resolve) => { - const checkInterval = setInterval(() => { - if (tcpCommunicator.hasResponseArrived()) { - clearInterval(checkInterval); - resolve(tcpCommunicator.getLastResult()); - } - }, 100); - }); - } - - // Method to stop all intervals (for cleanup if needed) - public stopAllIntervals(): void { - for (const id of this.intervalIds) { - clearInterval(id); - } - this.log("All intervals have been stopped.", 'log', 'stopAllIntervals'); - } -} \ No newline at end of file diff --git a/CEO/src/helpers/queue_manager.ts b/CEO/src/helpers/queue_manager.ts deleted file mode 100644 index cc3aeb0..0000000 --- a/CEO/src/helpers/queue_manager.ts +++ /dev/null @@ -1,137 +0,0 @@ -import fs from 'fs'; -import path from 'path'; - -export class QueueManager { - private readonly filePath: string; - private readonly lockFilePath: string; - private queue: T[]; - private readonly compareFn: (a: T, b: T) => boolean; // Comparison function - - constructor(filePath: string, compareFn: (a: T, b: T) => boolean) { - this.filePath = filePath; - this.lockFilePath = `${filePath}.lock`; // Define the lock file path - this.queue = []; - this.compareFn = compareFn; - - const dir = path.dirname(filePath); - - // Check if the directory exists, throw error if it doesn't - if (!fs.existsSync(dir)) { - throw new Error(`The directory does not exist: ${dir}`); - } - - // If the file doesn't exist, create it - if (!fs.existsSync(filePath)) { - fs.writeFileSync(filePath, JSON.stringify([], null, 2), 'utf8'); - } - } - - // Method to acquire a lock (create .lock file) - private acquireLock(): void { - while (fs.existsSync(this.lockFilePath)) { - // Wait until the lock file is released - this.sleepSync(100); // 100ms delay before retrying - } - // Create the lock file - fs.writeFileSync(this.lockFilePath, ''); - } - - // Sleep function to simulate delay for locking mechanism - private sleepSync(ms: number): void { - const start = Date.now(); - while (Date.now() - start < ms) { - // busy wait - } - } - - // Method to release the lock (delete .lock file) - private releaseLock(): void { - if (fs.existsSync(this.lockFilePath)) { - fs.unlinkSync(this.lockFilePath); - } - } - - // Load the queue from the JSON file - loadQueue(): void { - this.acquireLock(); // Acquire the lock - - try { - const fileData = fs.readFileSync(this.filePath, 'utf8'); - this.queue = JSON.parse(fileData) || []; - } catch (err) { - // If the file doesn't exist or is invalid, start with an empty queue - this.queue = []; - } finally { - this.releaseLock(); // Release the lock - } - } - - // Save the queue back to the JSON file - saveQueue(): void { - this.acquireLock(); // Acquire the lock - - try { - fs.writeFileSync(this.filePath, JSON.stringify(this.queue, null, 2), 'utf8'); - } finally { - this.releaseLock(); // Release the lock - } - } - - // Enqueue: Add an item to the end of the queue if it doesn't already exist - enqueue(item: T): void { - this.loadQueue(); // Ensure we load the latest queue - - // Check if the item already exists in the queue - const exists = this.queue.some(existingItem => this.compareFn(existingItem, item)); - - console.log(this.queue); - - if (!exists) { - this.queue.push(item); - this.saveQueue(); // Save the updated queue - } else { - console.log('Item already exists in the queue. Skipping enqueue.'); - } - } - - // Dequeue: Remove an item from the front of the queue - dequeue(): T | null { - this.loadQueue(); // Ensure we load the latest queue - if (this.queue.length === 0) { - return null; // Queue is empty - } - const item = this.queue.shift() as T; // Remove the first item - this.saveQueue(); // Save the updated queue - return item; - } - - // Peek: Get the item at the front of the queue without removing it - peek(): T | null { - this.loadQueue(); // Ensure we load the latest queue - return this.queue.length > 0 ? this.queue[0] : null; - } - - // Check if the queue is empty - isEmpty(): boolean { - this.loadQueue(); // Ensure we load the latest queue - return this.queue.length === 0; - } - - // Get the length of the queue - length(): number { - this.loadQueue(); // Ensure we load the latest queue - return this.queue.length; - } - - // Clear the entire queue - clearQueue(): void { - this.acquireLock(); // Acquire the lock - - try { - this.queue = []; // Clear the queue - fs.writeFileSync(this.filePath, JSON.stringify(this.queue, null, 2), 'utf8'); - } finally { - this.releaseLock(); // Release the lock - } - } -} diff --git a/CEO/src/helpers/tcp_communicator.ts b/CEO/src/helpers/tcp_communicator.ts deleted file mode 100644 index 648b71a..0000000 --- a/CEO/src/helpers/tcp_communicator.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { TcpClient } from "../network/tcp/tcp_client"; -import { ParsedMessage } from "../network/message_handler"; - -export class TcpCommunicator { - private readonly ip: string; - private readonly port: number; - private tcpClient: TcpClient | null = null; - private lastResult: ParsedMessage | null = null; - - constructor(ip: string, port: number) { - this.ip = ip; - this.port = port; - } - - async connect(): Promise { - this.tcpClient = new TcpClient(this.port); - this.tcpClient.openSocket(this.ip); - return this.tcpClient.isSocketConnected(); - } - - async sendMessage(operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer): Promise { - if (!this.tcpClient || !this.tcpClient.isSocketConnected()) return false; - - // Wait until the AES key is set before sending the message - return new Promise((resolve) => { - const idWaitForAes = setInterval(async () => { - if (this.tcpClient?.isAesKeySet()) { - clearInterval(idWaitForAes); - - // Send the message once AES key is set - const status = await this.tcpClient!.sendMessage(operationCode, metaInfo, fileContent); - - if (status) { - await this.waitForResponse(); - } - - resolve(status); - } - }, 100); - }); - } - - getLastResult(): ParsedMessage | null { - const message = this.lastResult; - this.lastResult = null; - - if (global.gc) { - global.gc(); - } - - return message; - } - - hasResponseArrived(): boolean { - if(!this.tcpClient) return false; - return this.lastResult !== null; - } - - private waitForResponse(): Promise { - return new Promise((resolve, reject) => { - if (!this.tcpClient) { - reject(); - } - - // Start interval for waiting for the response - const responseInterval = setInterval(() => { - if (!this.tcpClient?.isSocketConnected()) { - clearInterval(responseInterval); - resolve(); - } - - if (this.tcpClient?.isMessageReceived()) { - this.lastResult = this.tcpClient.getLastResult(); - clearInterval(responseInterval); // Stop checking once we have a response - resolve(); - } - }, 100); // Check every 100 milliseconds - }); - } - - async disconnect(): Promise { - if (!this.tcpClient || !this.tcpClient.isSocketConnected()) return true; - this.tcpClient.closeSocket(); - return true; - } -} diff --git a/CEO/src/helpers/users_info_fetcher.ts b/CEO/src/helpers/users_info_fetcher.ts deleted file mode 100644 index 2852b04..0000000 --- a/CEO/src/helpers/users_info_fetcher.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { JsonManager } from "./json_manager"; -import { MemoryManager } from "./memory_manager"; -import { operationCodes } from "../network/operation_codes"; -import { TcpCommunicator } from "./tcp_communicator"; -import { ParsedMessage } from "../network/message_handler"; - -export class UsersInfoFetcher { - private applicationInfo: JsonManager; - private memoryManager: MemoryManager; - private tcpCommunicator: TcpCommunicator | null = null; - private readonly clientPort: number; - private memoryId: string; - private readonly activeUsersKey: string; - private intervalId: NodeJS.Timeout | null = null; - - constructor(applicationInfoPath: string, memoryManagerPath: string, clientPort: number) { - this.applicationInfo = new JsonManager(applicationInfoPath); - this.memoryManager = new MemoryManager(memoryManagerPath); - this.memoryId = ''; - this.clientPort = clientPort; - this.tcpCommunicator = null; - this.activeUsersKey = 'active_users_info'; - } - - // Method to start checking user info periodically (every minute) - async start(): Promise { - this.intervalId = setInterval(async () => { - await this.initialize(); // Re-run every minute - - if (global.gc) { - global.gc(); - } - }, 5000); // 5-second interval for testing - } - - // Initialize and fetch user IPs and process users info - private async initialize() { - const usersIps = await this.applicationInfo.readValue('users_ip'); - if (!usersIps) { - this.log('No IP addresses found in users_ip', 'error'); - return; - } - - // Ensure active_users_info exists in the memory - this.memoryId = await this.applicationInfo.readValue(this.activeUsersKey); - if (!this.memoryId) { - this.memoryId = await this.memoryManager.storeMetaInformation([]); - await this.applicationInfo.writeValue(this.activeUsersKey, this.memoryId); - } - - // Check user information - await this.checkUsersInfo(usersIps); - } - - // Check user info from the list of IPs - private async checkUsersInfo(usersIps: string[]) { - let usersInfo: Array<{ ip: string, user_info: any }> = []; // Array to store IP and user_info objects - - for (const ip of usersIps) { - this.tcpCommunicator = new TcpCommunicator(ip, this.clientPort); - if (!await this.tcpCommunicator.connect()) { - this.log(`Failed to open connection for IP: ${ip}`, 'error'); - continue; - } - - if(!await this.tcpCommunicator?.sendMessage(operationCodes.GET_USER_INFORMATION)){ - await this.tcpCommunicator.disconnect(); - continue; - } - - // Wait for the response for 10 seconds - const response = await this.waitForResponse(); - - // If a response is received and is successful, append it to usersInfo - if (response && response.metaInfo) { - usersInfo.push({ - ip: ip, - user_info: response.metaInfo - }); - } - - await this.tcpCommunicator.disconnect(); - } - - await this.updateActiveUsers(usersInfo); // Update active users information in the memory - } - - private async waitForResponse(): Promise { - return new Promise((resolve) => { - const idResponseCheck = setInterval(async () => { - if (!this.tcpCommunicator) return null; - if (this.tcpCommunicator.hasResponseArrived()) { - clearInterval(idResponseCheck); - resolve(this.tcpCommunicator.getLastResult()); // Resolve the response or null if not available - } - }, 100); // Check every 100 milliseconds if the response has arrived - }); - } - - // Update active users information in the memory - private async updateActiveUsers(userInfo: any[]) { - await this.memoryManager.updateMetaInformation(this.memoryId, userInfo); // Update active users in memory - } - - stop(): void { - if (this.intervalId) { - clearInterval(this.intervalId); - this.intervalId = null; - console.log("[UsersInfoFetcher] Stopped successfully."); - } - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[UsersInfoFetcher]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } -} diff --git a/CEO/src/helpers/window_manager.ts b/CEO/src/helpers/window_manager.ts deleted file mode 100644 index 97abfc3..0000000 --- a/CEO/src/helpers/window_manager.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { BrowserWindow, dialog, shell } from 'electron'; -import fs from 'fs'; -import path from 'path'; - -export class WindowManager { - private readonly mainWindow: BrowserWindow; - private readonly pathToPagesDir: string; - private announcementWindow: BrowserWindow | null = null; - - constructor(mainWindow: BrowserWindow, pathToPagesDir: string) { - this.pathToPagesDir = pathToPagesDir; - this.mainWindow = mainWindow; - this.log('WindowManager initialized.'); - } - - // Logging helper function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[WindowManager]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - // Show an alert dialog - async showAlert(message: string): Promise { - if (this.mainWindow) { - await dialog.showMessageBox(this.mainWindow, { - type: 'info', - title: 'Alert', - message: message, - buttons: ['OK'], - }); - this.log(`Alert displayed with message: "${message}"`); - } else { - this.log('Main window is not available.', 'error'); - } - } - - // Change the content of the current window to load a new HTML file - async changeContent(destination: string): Promise { - if (this.mainWindow) { - try { - const destinationPath = path.join(this.pathToPagesDir, `${destination}.html`); - this.log(`Navigating to: ${destinationPath}`); - - // Load the destination HTML file into the main window - await this.mainWindow.loadFile(destinationPath); - this.log(`Navigated to ${destination}`); - } catch (error) { - this.log(`Error changing content: ${error}`, 'error'); - throw error; // Pass the error back to the render process - } - } else { - this.log('Main window is not available.', 'error'); - } - } - - // New method to select a directory - async selectDirectory(): Promise { - const result = await dialog.showOpenDialog(this.mainWindow, { - properties: ['openDirectory'], // Only allow selecting directories - }); - - if (result.filePaths && result.filePaths.length > 0) { - this.log(`Directory selected: ${result.filePaths[0]}`); - return result.filePaths[0]; // Return the selected directory path - } else { - this.log('No directory selected.'); - return undefined; // Return undefined if no directory was selected - } - } - - // Show a file in the explorer - async showFileInExplorer(filePath: string): Promise { - if (filePath && fs.existsSync(filePath)) { - try { - shell.showItemInFolder(filePath); - this.log(`Opened file explorer for: ${filePath}`); - } catch (error: any) { - this.log(`Error showing file in explorer: ${error.message}`, 'error'); - } - } else { - this.log('File path is undefined or does not exist.', 'error'); - } - } - - // New method to open the file explorer and choose a file - async selectFile(): Promise { - const result = await dialog.showOpenDialog(this.mainWindow, { - properties: ['openFile'], // Allow selecting a file - filters: [ - { name: 'All Files', extensions: ['*'] } // Optionally filter for specific file types - ] - }); - - if (result.filePaths && result.filePaths.length > 0) { - this.log(`File selected: ${result.filePaths[0]}`); - return result.filePaths[0]; // Return the selected file path - } else { - this.log('No file selected.'); - return undefined; // Return undefined if no file was selected - } - } - - // Method to display an announcement in a new window - async displayAnnouncement(): Promise { - if (this.announcementWindow) { - this.announcementWindow.focus(); - this.log('Announcement window focused.'); - return; - } - - const mainScreen = require('electron').screen.getPrimaryDisplay(); - const { width, height } = mainScreen.size; - - this.announcementWindow = new BrowserWindow({ - width: width / 3, - height: height / 2, - resizable: false, - title: 'Announcement', - webPreferences: { - preload: path.join(__dirname, '..', 'main', 'preload.js'), - contextIsolation: true, - nodeIntegration: false, - }, - }); - - this.announcementWindow.removeMenu(); - const announcementPath = path.join(this.pathToPagesDir, 'announcement.html'); - await this.announcementWindow.loadFile(announcementPath); - - this.log(`Announcement window opened at: ${announcementPath}`); - - // Handle window close - this.announcementWindow.on('closed', () => { - this.announcementWindow = null; - this.log('Announcement window closed.'); - }); - } - - async closeAnnouncementWindow(): Promise { - if (this.announcementWindow) { - this.announcementWindow.close(); - this.log('Announcement window closed by user.'); - } - } -} diff --git a/CEO/src/helpers/worker_manager.ts b/CEO/src/helpers/worker_manager.ts deleted file mode 100644 index 7a9ae9f..0000000 --- a/CEO/src/helpers/worker_manager.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { fork, ChildProcess } from 'child_process'; -import path from 'path'; -import { WindowManager } from "./window_manager"; - -export class WorkerManager { - private readonly pathToWorkerDir: string; - private windowManager: WindowManager; - private workers: ChildProcess[]; - private cleanupInProgress: boolean = false; - - constructor(pathToWorkerDir: string, windowManager: WindowManager) { - this.pathToWorkerDir = pathToWorkerDir; - this.windowManager = windowManager; - this.workers = []; - } - - async startNetworkScannerWorker(udpPort: number, tcpPort: number, okPage: string, errorPage: string, databaseResetPage: string, userConfigPath: string, applicationInfoPath: string): Promise { - return this.startForkedWorker('network_scanner_worker.js', { - UDP_PORT: udpPort.toString(), - TCP_PORT: tcpPort.toString(), - OK_PAGE: okPage, - ERROR_PAGE: errorPage, - DATABASE_RESET_PAGE: databaseResetPage, - USER_CONFIG_PATH: userConfigPath, - APPLICATION_INFO_PATH: applicationInfoPath - }); - } - - async startDirectoriesWatchersWorker(memoryManagerPath: string, applicationInfoPath: string): Promise { - return this.startForkedWorker('directories_watcher_worker.js', { - MEMORY_MANAGER_PATH: memoryManagerPath, - APPLICATION_INFO_PATH: applicationInfoPath - }); - } - - async startServersWorker(host: string, udpPort: number, tcpPort: number): Promise { - return this.startForkedWorker('servers_worker.js', { - HOST: host, - USER_UDP_PORT: udpPort.toString(), - USER_TCP_PORT: tcpPort.toString() - }); - } - - async startResourceCoordinatorWorker(usersConfigPath: string, applicationInfoPath: string, memoryManagerPath: string, queueManagerPath: string, tcpPort: number): Promise { - return this.startForkedWorker('resource_coordinator_worker.js', { - USERS_CONFIG_PATH: usersConfigPath, - APPLICATION_INFO_PATH: applicationInfoPath, - MEMORY_MANAGER_PATH: memoryManagerPath, - QUEUE_MANAGER_PATH: queueManagerPath, - TCP_PORT: tcpPort.toString() - }); - } - - async startBackupRetrievalWorker(userConfigPath: string, applicationInfoPath: string, clientPort: number, destinationPath: string): Promise { - return this.startForkedWorker('backup_retrieval_worker.js', { - USER_CONFIG_PATH: userConfigPath, - APPLICATION_INFO_PATH: applicationInfoPath, - CLIENT_PORT: clientPort.toString(), - DESTINATION_PATH: destinationPath - }); - } - - async startAnnouncementWorker(applicationInfoPath: string, clientPort: number, message: string): Promise { - return this.startForkedWorker('send_announcement_worker.js', { - APPLICATION_INFO_PATH: applicationInfoPath, - CLIENT_PORT: clientPort.toString(), - MESSAGE: message - }); - } - - private async startForkedWorker(scriptName: string, envData: { [key: string]: string }): Promise { - return new Promise((resolve, reject) => { - const worker = fork(path.join(this.pathToWorkerDir, scriptName), { - execArgv: ['--max-old-space-size=4096'], - env: { ...process.env, ...envData } - }); - - this.workers.push(worker); - - worker.on('message', (data: unknown) => { - const message = data as { type: string, page?: string, message?: string }; - - if (message.type === 'changeContent' && message.page) { - this.windowManager.changeContent(message.page); - } else if (message.type === 'showAlert' && message.message) { - this.windowManager.showAlert(message.message); - } else { - console.log(`${scriptName} message:`, message); - } - }); - - worker.on('error', (err) => { - console.error(`${scriptName} error:`, err); - worker.kill(); - this.removeWorker(worker); - reject(err); - }); - - worker.on('exit', (code, signal) => { - this.removeWorker(worker); - if (code === 0) { - console.log(`${scriptName} exited successfully`); - resolve(); - } else if (signal) { - console.log(`${scriptName} was killed with signal: ${signal}`); - } else { - console.error(`${scriptName} exited with code: ${code}`); - } - }); - }); - } - - closeAllWorkers(): void { - if (this.cleanupInProgress) return; - this.cleanupInProgress = true; - - console.log('Terminating all running workers...'); - this.workers.forEach(worker => worker.kill()); - this.workers = []; - } - - private removeWorker(worker: ChildProcess): void { - const index = this.workers.indexOf(worker); - if (index > -1) { - this.workers.splice(index, 1); - } - } -} diff --git a/CEO/src/interfaces/file_item_task.ts b/CEO/src/interfaces/file_item_task.ts deleted file mode 100644 index 6934379..0000000 --- a/CEO/src/interfaces/file_item_task.ts +++ /dev/null @@ -1,8 +0,0 @@ -export interface FileItemTask { - ip: string; - path: string; - userName: string; -} - -export const compareFnFileItemTask = (task1: FileItemTask, task2: FileItemTask) => - task1.ip === task2.ip && task1.path === task2.path; diff --git a/CEO/src/interfaces/pool_request.ts b/CEO/src/interfaces/pool_request.ts deleted file mode 100644 index 73e9302..0000000 --- a/CEO/src/interfaces/pool_request.ts +++ /dev/null @@ -1,15 +0,0 @@ -interface PoolRequest { - type: PoolOperation; // Renamed to PoolOperation - clientId: string; // Add clientId to the request - data: PoolDataBundle; -} - -interface PoolDataBundle { - port?: number; - ip?: string; - operationCode?: string; // Keep operationCode here - metaInfo?: { [key: string]: any }; - fileContent?: Buffer; -} - -type PoolOperation = 'open' | 'send' | 'close'; // Define the allowed PoolOperations diff --git a/CEO/src/interfaces/registered_client.ts b/CEO/src/interfaces/registered_client.ts deleted file mode 100644 index 71ac44b..0000000 --- a/CEO/src/interfaces/registered_client.ts +++ /dev/null @@ -1,5 +0,0 @@ -interface RegisteredClient { - id: string; - ip: string; - port: number; -} \ No newline at end of file diff --git a/CEO/src/main/main.ts b/CEO/src/main/main.ts deleted file mode 100644 index 5de4a6c..0000000 --- a/CEO/src/main/main.ts +++ /dev/null @@ -1,363 +0,0 @@ -import {app, BrowserWindow, ipcMain, IpcMainInvokeEvent} from 'electron'; -import path from 'path'; -import { promises as fs } from 'fs'; -import dotenv from 'dotenv'; - -import {WorkerManager} from "../helpers/worker_manager"; -import {DirectoryWatcher} from "../helpers/directory_watcher"; -import {QueueManager} from "../helpers/queue_manager"; -import {compareFnFileItemTask, FileItemTask} from "../interfaces/file_item_task"; -import {WindowManager} from "../helpers/window_manager"; -import {JsonManager} from "../helpers/json_manager"; -import {MemoryManager} from "../helpers/memory_manager"; -import {TcpCommunicator} from "../helpers/tcp_communicator"; - -import {operationCodes} from "../network/operation_codes"; -import os from "os"; - -// Load environment variables -dotenv.config({ path: path.join(__dirname, '..', '..', '.env') }); - -const UDP_PORT = process.env.UDP_PORT ? parseInt(process.env.UDP_PORT) : 41233; -const TCP_PORT = process.env.TCP_PORT ? parseInt(process.env.TCP_PORT) : 41234; -const HOST = getLocalIp(); - -let mainWindow: BrowserWindow | null = null; -let windowManager: WindowManager | null = null; -let tcpCommunicator: TcpCommunicator | null = null; -let userConfig: JsonManager | null = null; -let applicationInfo: JsonManager | null = null; -let memoryManager: MemoryManager | null = null; -let workerManager: WorkerManager | null = null; -let backupDirectoryManager: DirectoryWatcher | null = null; -let departmentShareManager: DirectoryWatcher | null = null; -let sendFileQueue: QueueManager | null = null; - -const pathToPagesDir = path.join(__dirname, '..', '..', 'render', 'html'); -const pathToWorkerDir = path.join(__dirname, '..', 'workers'); -const pathToJsons = path.join(__dirname, '..', 'json_files'); -const pathToClientsBackups = path.join(__dirname, '..', 'backups'); - -async function cleanupAndExit() { - // Stop all workers - if (workerManager) { - console.log('Terminating all workers...'); - workerManager.closeAllWorkers(); - } - - // Reset memory - if (memoryManager) { - await memoryManager.resetFile(); - } - - // Close watchers - if (backupDirectoryManager) { - console.log('Stopping backup directory watcher...'); - backupDirectoryManager.closeWatcher(); // Add this method to DirectoryWatcher to close the watcher - } - - if (departmentShareManager) { - console.log('Stopping department directory watcher...'); - departmentShareManager.closeWatcher(); // Add this method to DirectoryWatcher to close the watcher - } - - if(workerManager){ - console.log('Terminating all workers...'); - workerManager.closeAllWorkers() - } - - console.log('Cleanup complete, exiting application.'); - app.quit(); // This will properly close the application -} - -async function ensureDirectoryExists(dirPath: string): Promise { - try { - await fs.access(dirPath); - } catch (err) { - // If the directory doesn't exist, create it - await fs.mkdir(dirPath, { recursive: true }); - console.log(`Directory created: ${dirPath}`); - } -} - -function getLocalIp() { - const interfaces = os.networkInterfaces(); - for (let interfaceName in interfaces) { - const addresses = interfaces[interfaceName]; - if(!addresses) continue; - for (let address of addresses) { - // Filter for IPv4 and ignore internal (127.0.0.1) addresses - if (address.family === 'IPv4' && !address.internal) { - return address.address; - } - } - } - return ''; // Fallback if no IP is found -} - -app.whenReady().then(async () => { - const title = 'Application'; - const mainScreen = require('electron').screen.getPrimaryDisplay(); - const { width, height } = mainScreen.size; - - mainWindow = new BrowserWindow({ - title, - width: width / 1.5, - height: height / 1.5, - resizable: false, - webPreferences: { - preload: path.join(__dirname, 'preload.js'), - nodeIntegration: false, - contextIsolation: true, - }, - }); - - mainWindow.removeMenu(); - - await ensureDirectoryExists(pathToJsons); - await ensureDirectoryExists(pathToClientsBackups); - - windowManager = new WindowManager(mainWindow, pathToPagesDir); - userConfig = new JsonManager(path.join(pathToJsons, 'userConfig.json')); - applicationInfo = new JsonManager(path.join(pathToJsons, 'application.json')); - memoryManager = new MemoryManager(path.join(pathToJsons, 'memory.json')); - sendFileQueue = new QueueManager(path.join(pathToJsons, 'sendFileTasks.json'), compareFnFileItemTask); - - workerManager = new WorkerManager(pathToWorkerDir, windowManager); - - await userConfig.writeValue('app_type', 'ceo'); - await applicationInfo.writeValue('users_ip', []); - await applicationInfo.writeValue('serverIp', ''); - await applicationInfo.writeValue('announcement', ''); - await memoryManager.resetFile(); - - workerManager.startNetworkScannerWorker(UDP_PORT, TCP_PORT, 'login', 'uc_not_found', 'reset_database', path.join(pathToJsons, 'userConfig.json'), path.join(pathToJsons, 'application.json')); - workerManager.startDirectoriesWatchersWorker(path.join(pathToJsons, 'memory.json'), path.join(pathToJsons, 'application.json')); - workerManager.startServersWorker(HOST, UDP_PORT, TCP_PORT); - workerManager.startResourceCoordinatorWorker( - path.join(pathToJsons, 'userConfig.json'), - path.join(pathToJsons, 'application.json'), - path.join(pathToJsons, 'memory.json'), - path.join(pathToJsons, 'sendFileTasks.json'), - TCP_PORT - ); - - registerIPCHandlers(); - - await windowManager.changeContent('welcome'); -}); - -app.on('window-all-closed', async () => { - console.log('All windows closed, starting cleanup...'); - await cleanupAndExit(); // Call cleanup when all windows are closed -}); - -// Catch CTRL+C (SIGINT) and clean up resources -process.on('SIGINT', async () => { - console.log('CTRL+C pressed, starting cleanup...'); - await cleanupAndExit(); // Call cleanup on SIGINT -}); - -app.on('before-quit', async () => { - console.log('Application is quitting, starting cleanup...'); - await cleanupAndExit(); // Call cleanup before app quit -}); - -// Register IPC handlers -function registerIPCHandlers() { - // ResetApplicationPreferences IPC Handlers - ipcMain.handle('reset-application-preferences', async () => { - if(applicationInfo) { - const serverIp = await applicationInfo.readValue('serverIp'); - await applicationInfo.resetFile(); - await applicationInfo.writeValue('serverIp', serverIp); - } - - if(userConfig) { - await userConfig.resetFile(); - await userConfig.writeValue('app_type', 'ceo'); - } - - if(memoryManager) { - await memoryManager.resetFile(); - } - - if(sendFileQueue) { - sendFileQueue.clearQueue(); - } - - if(workerManager) { - workerManager.closeAllWorkers(); - await new Promise(resolve => setTimeout(resolve, 3000)); - workerManager.startNetworkScannerWorker(UDP_PORT, TCP_PORT, 'login', 'uc_not_found', 'reset_database', path.join(pathToJsons, 'userConfig.json'), path.join(pathToJsons, 'application.json')); - workerManager.startDirectoriesWatchersWorker(path.join(pathToJsons, 'memory.json'), path.join(pathToJsons, 'application.json')); - workerManager.startServersWorker(HOST, UDP_PORT, TCP_PORT); - workerManager.startResourceCoordinatorWorker( - path.join(pathToJsons, 'userConfig.json'), - path.join(pathToJsons, 'application.json'), - path.join(pathToJsons, 'memory.json'), - path.join(pathToJsons, 'sendFileTasks.json'), - TCP_PORT - ); - } - }); - - // Window Manager IPC Handlers - ipcMain.handle('show-alert', async (event: IpcMainInvokeEvent, message: string) => { - if (!windowManager) throw new Error('WindowManager is not initialized.'); - await windowManager.showAlert(message); - }); - - ipcMain.handle('change-content', async (_event: IpcMainInvokeEvent, destination: string) => { - if (!windowManager) throw new Error('WindowManager is not initialized.'); - await windowManager.changeContent(destination); - }); - - ipcMain.handle('select-directory', async (_event: IpcMainInvokeEvent) => { - if (!windowManager) throw new Error('WindowManager is not initialized.'); - return await windowManager.selectDirectory(); - }); - - ipcMain.handle('select-file', async (_event: IpcMainInvokeEvent) => { - if (!windowManager) throw new Error('WindowManager is not initialized.'); - return await windowManager.selectFile(); - }); - - ipcMain.handle('show-file-in-explorer', async (_event: IpcMainInvokeEvent, path: string) => { - if (!windowManager) throw new Error('WindowManager is not initialized.'); - return await windowManager.showFileInExplorer(path); - }); - - // TcpMethods IPC Handlers - ipcMain.handle('open-socket', async (_event: IpcMainInvokeEvent) => { - if (!applicationInfo) throw new Error('TcpMethods is not initialized.'); - - const serverIp = await applicationInfo.readValue('serverIp'); - if (!serverIp) return; - - tcpCommunicator = new TcpCommunicator(serverIp, TCP_PORT); - return await tcpCommunicator.connect() - }); - - ipcMain.handle('send-message', async (_event: IpcMainInvokeEvent, operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer) => { - if (!tcpCommunicator) throw new Error('TcpMethods is not initialized.'); - return await tcpCommunicator.sendMessage(operationCode, metaInfo, fileContent); - }); - - ipcMain.handle('has-response-arrived', async (_event: IpcMainInvokeEvent) => { - if (!tcpCommunicator) throw new Error('TcpMethods is not initialized.'); - return tcpCommunicator.hasResponseArrived(); - }); - - ipcMain.handle('close-socket', async (_event: IpcMainInvokeEvent) => { - if (!tcpCommunicator) throw new Error('TcpMethods is not initialized.'); - return await tcpCommunicator.disconnect(); - }); - - ipcMain.handle('get-last-result', async (_event: IpcMainInvokeEvent) => { - if (!tcpCommunicator) throw new Error('TcpMethods is not initialized.'); - return tcpCommunicator.getLastResult(); - }); - - ipcMain.handle('get-operation-codes', () => { - return operationCodes; - }); - - // UserConfig IPC Handlers - ipcMain.handle('read-user-json-files', async (_event: IpcMainInvokeEvent, key: string) => { - if (!userConfig) throw new Error('UserConfig is not initialized.'); - return await userConfig.readValue(key); - }); - - ipcMain.handle('write-user-json-files', async (_event: IpcMainInvokeEvent, key: string, value: any) => { - if (!userConfig) throw new Error('UserConfig is not initialized.'); - return userConfig.writeValue(key, value); - }); - - ipcMain.handle('reset-user-json-files', async () => { - if (!userConfig) throw new Error('UserConfig is not initialized.'); - return userConfig.resetFile(); - }); - - ipcMain.handle('remove-user-json-files-key', async (_event: IpcMainInvokeEvent, key: string) => { - if (!userConfig) throw new Error('UserConfig is not initialized.'); - return userConfig.removeValue(key); - }); - - // ApplicationPreferences IPC Handlers - ipcMain.handle('read-application-json-files', async (_event: IpcMainInvokeEvent, key: string) => { - if (!applicationInfo) throw new Error('ApplicationInfo is not initialized.'); - return await applicationInfo.readValue(key); - }); - - ipcMain.handle('write-application-json-files', async (_event: IpcMainInvokeEvent, key: string, value: any) => { - if (!applicationInfo) throw new Error('ApplicationInfo is not initialized.'); - return applicationInfo.writeValue(key, value); - }); - - ipcMain.handle('reset-application-json-files', async () => { - if (!applicationInfo) throw new Error('ApplicationInfo is not initialized.'); - const serverIp = await applicationInfo.readValue('serverIp'); - await applicationInfo.resetFile(); - if(serverIp) { - await applicationInfo.writeValue('serverIp', serverIp); - } - }); - - ipcMain.handle('remove-application-json-files-key', async (_event: IpcMainInvokeEvent, key: string) => { - if (!applicationInfo) throw new Error('ApplicationInfo is not initialized.'); - return applicationInfo.removeValue(key); - }); - - // Memory IPC Handlers - ipcMain.handle('memory-create-entry', async () => { - if (!memoryManager) throw new Error('MemoryManager is not initialized.'); - return memoryManager.storeMetaInformation({}); - }); - - ipcMain.handle('memory-read-entry', async (_event: IpcMainInvokeEvent, id: string) => { - if (!memoryManager) throw new Error('MemoryManager is not initialized.'); - return memoryManager.retrieveMetaInformation(id); - }); - - ipcMain.handle('memory-update-entry', async (_event: IpcMainInvokeEvent, id: string, data: any) => { - if (!memoryManager) throw new Error('MemoryManager is not initialized.'); - return memoryManager.updateMetaInformation(id, data); - }); - - ipcMain.handle('memory-remove-entry', async (_event: IpcMainInvokeEvent, id: string) => { - if (!memoryManager) throw new Error('MemoryManager is not initialized.'); - return memoryManager.removeMetaInformation(id); - }); - - ipcMain.handle('memory-reset', async () => { - if (!memoryManager) throw new Error('MemoryManager is not initialized.'); - return memoryManager.resetFile(); - }); - - // Queue IPC Handlers - ipcMain.handle('add-task-to-send-file-queue', async (event: IpcMainInvokeEvent, task: FileItemTask) => { - if (!sendFileQueue) throw new Error('SendFileQueue is not initialized.'); - sendFileQueue.enqueue(task); - }); - - // Workers IPC Handlers - ipcMain.handle('start-backup-retrieval', async (_event: IpcMainInvokeEvent, destinationPath: string) => { - if (!workerManager) throw new Error('WorkerManager is not initialized.'); - return workerManager.startBackupRetrievalWorker( - path.join(pathToJsons, 'userConfig.json'), - path.join(pathToJsons, 'application.json'), - TCP_PORT, - destinationPath - ); - }); - - ipcMain.handle('start-announcement-worker', async (_event: IpcMainInvokeEvent, message: string) => { - if (!workerManager) throw new Error('WorkerManager is not initialized.'); - return workerManager.startAnnouncementWorker( - path.join(pathToJsons, 'application.json'), - TCP_PORT, - message - ); - }); -} \ No newline at end of file diff --git a/CEO/src/main/preload.ts b/CEO/src/main/preload.ts deleted file mode 100644 index 2643ba9..0000000 --- a/CEO/src/main/preload.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { contextBridge, ipcRenderer } from 'electron'; -import {FileItemTask} from "../interfaces/file_item_task"; - -contextBridge.exposeInMainWorld('electronAPI', { - // UserConfig methods - readUserConfig: (key: string): Promise => ipcRenderer.invoke('read-user-json-files', key), - writeUserConfig: (key: string, value: any): Promise => ipcRenderer.invoke('write-user-json-files', key, value), - removeUserConfig: (key: string) : Promise => ipcRenderer.invoke('remove-user-json-files', key), - resetUserConfig: (): Promise => ipcRenderer.invoke('reset-user-json-files'), - - // ApplicationPreferences methods - readApplicationInfo: (key: string): Promise => ipcRenderer.invoke('read-application-json-files', key), - writeApplicationInfo: (key: string, value: any): Promise => ipcRenderer.invoke('write-application-json-files', key, value), - removeApplicationInfo: (key: string) : Promise => ipcRenderer.invoke('remove-application-preferences', key), - resetApplicationInfo: (): Promise => ipcRenderer.invoke('reset-application-json-files'), - - // UcCommunication methods - openUcSocket: (): Promise => ipcRenderer.invoke('open-socket'), - sendUcMessage: (operationCode: string, metaInfo: any, fileContent: any): Promise => ipcRenderer.invoke('send-message', operationCode, metaInfo, fileContent), - closeUcSocket: (): Promise => ipcRenderer.invoke('close-socket'), - hasResponseArrived: (): Promise => ipcRenderer.invoke('has-response-arrived'), - getLastUcResult: (): Promise => ipcRenderer.invoke('get-last-result'), - getOperationsCodes: (): Promise<{ data: { [key: string]: string } }> => ipcRenderer.invoke('get-operation-codes'), - - // MemoryManager methods - createMemoryEntry: (): Promise => ipcRenderer.invoke('memory-create-entry'), - readMemoryEntry: (id: string): Promise => ipcRenderer.invoke('memory-read-entry', id), - updateMemoryEntry: (id: string, data: any): Promise => ipcRenderer.invoke('memory-update-entry', id, data), - removeMemoryEntry: (id: string): Promise => ipcRenderer.invoke('memory-remove-entry', id), - resetMemory: (): Promise => ipcRenderer.invoke('memory-reset'), - - // UI methods - showAlert: (message: string): Promise => ipcRenderer.invoke('show-alert', message), - changeContent: (destination: string): Promise => ipcRenderer.invoke('change-content', destination), - selectDirectory: (): Promise => ipcRenderer.invoke('select-directory'), - selectFile: (): Promise => ipcRenderer.invoke('select-file'), - showFileInExplorer: (path: string): Promise => ipcRenderer.invoke('show-file-in-explorer', path), - - // Queue methods - addTaskToSendFileQueue: (task: FileItemTask): Promise => ipcRenderer.invoke('add-task-to-send-file-queue', task), - - // Workers - startBackupRetrieval: (destinationPath: string): Promise => ipcRenderer.invoke('start-backup-retrieval', destinationPath), - startAnnouncementWorker: (message: string): Promise => ipcRenderer.invoke('start-announcement-worker', message), -}); diff --git a/CEO/src/network/connection_manager.ts b/CEO/src/network/connection_manager.ts deleted file mode 100644 index 6dba3eb..0000000 --- a/CEO/src/network/connection_manager.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { SocketCommunicatorBase } from "./socket_communicator/socket_communicator_base"; - -interface Connection { - communicator: SocketCommunicatorBase; -} - -export class ConnectionManager { - private readonly connections: { [key: string]: Connection }; - - constructor() { - this.connections = {}; - } - - // Adds a new communicator, keyed by both IP and port - addConnection(ip: string, port: number, communicator: SocketCommunicatorBase): void { - const key = `${ip}:${port}`; - - // Store the communicator along with the client's public and private keys - this.connections[key] = { - communicator - }; - } - - // Removes a communicator based on IP and port - removeCommunicator(ip: string, port: number): void { - const key = `${ip}:${port}`; - if (this.connections[key]) { - delete this.connections[key]; - } - } - - // Retrieves a communicator based on IP and port - getCommunicator(ip: string, port: number): SocketCommunicatorBase | null { - const key = `${ip}:${port}`; - return this.connections[key] ? this.connections[key].communicator : null; - } - - // Checks if a communicator exists for a given IP and port - communicatorExists(ip: string, port: number): boolean { - const key = `${ip}:${port}`; - return this.connections[key] !== undefined; - } -} diff --git a/CEO/src/network/message_handler.ts b/CEO/src/network/message_handler.ts deleted file mode 100644 index 6583a1d..0000000 --- a/CEO/src/network/message_handler.ts +++ /dev/null @@ -1,65 +0,0 @@ -export interface ParsedMessage { - operationCode: string; - metaInfo?: { [key: string]: any }; - fileContent?: Buffer; -} - -export class MessageHandler { - // Format the message with operationCode, guid, metaInfo, and fileContent (Base64 for fileContent) - static formatMessage( - operationCode: string, - metaInfo?: { [key: string]: any }, - fileContent?: Buffer - ): string { - let message = `${operationCode}\n`; // First part: operationCode and guid - - if (metaInfo && Object.keys(metaInfo).length > 0) { - message += `${JSON.stringify(metaInfo)}\n`; // Add metaInfo - } - - if (fileContent && fileContent.length > 0) { - message += fileContent.toString('base64'); // Convert buffer to Base64 for fileContent - } - - return message; - } - - // Parse the incoming message (convert Base64 back to Buffer if fileContent is present) - static parseMessage(msg: string): ParsedMessage { - const parts = msg.split('\n'); // Split by \n (operationCode, metaInfo, and fileContent are on separate lines) - - // First part should always be the operation code - const operationCode = parts[0]?.trim(); - if (!operationCode) { - throw new Error('Missing operation code in the message'); - } - - let metaInfo: { [key: string]: any } | undefined = undefined; - let fileContent: Buffer | undefined = undefined; - - // Parse the metaInfo (JSON object) if present - if (parts[1]) { - try { - metaInfo = JSON.parse(parts[1].trim()); - } catch (err) { - console.error('Invalid metaInfo JSON format:', err); - } - } - - // Convert Base64 string back to Buffer for fileContent if present - if (parts[2]) { - fileContent = Buffer.from(parts[2].trim(), 'base64'); - } - - return { - operationCode, - metaInfo, - fileContent, - }; - } - - // Validate if the parsed message contains an operation code - static validateMessage(parsedMessage: ParsedMessage | null): boolean { - return !!parsedMessage?.operationCode; - } -} \ No newline at end of file diff --git a/CEO/src/network/network.ts b/CEO/src/network/network.ts deleted file mode 100644 index 8f65956..0000000 --- a/CEO/src/network/network.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { UdpClient} from './udp/udp_client'; -export { TcpClient } from './tcp/tcp_client' \ No newline at end of file diff --git a/CEO/src/network/operation_codes.ts b/CEO/src/network/operation_codes.ts deleted file mode 100644 index fe7bd78..0000000 --- a/CEO/src/network/operation_codes.ts +++ /dev/null @@ -1,41 +0,0 @@ -export let operationCodes = { - // General Operations - ARE_YOU_HUMAN: 'ARE_YOU_HUMAN', - ARE_YOU_UC: 'ARE_YOU_UC', - ALIVE: 'ALIVE', - SET_PUBLIC_KEY: 'SET_PUBLIC_KEY', - SET_AES_KEY: 'SET_AES_KEY', - RESET_DATABASE: 'RESET_DATABASE', - OK: 'OK', - ERR: 'ERR', - END: 'END', - UNKNOWN_COMMAND: 'UNKNOWN_COMMAND', - - // Auth Operations - LOGIN: 'LOGIN', - SIGN_UP: 'SIGN_UP', - RESET_PASSWORD: 'RESET_PASSWORD', - - FIND_BY_EMAIL: 'FIND_BY_EMAIL', - MODIFY_USER: 'MODIFY_USER', - - GET_DEPARTMENTS: 'GET_DEPARTMENTS', - CREATE_DEPARTMENT: 'CREATE_DEPARTMENT', - MODIFY_DEPARTMENT: 'MODIFY_DEPARTMENT', - DELETE_DEPARTMENT: 'DELETE_DEPARTMENT', - - GET_USERS: 'GET_USERS', - FIND_KEY_BY_USER_ID: 'FIND_KEY_BY_USER_ID', - SEND_ANNOUNCEMENT: 'SEND_ANNOUNCEMENT', - - GET_USER_INFORMATION: 'GET_USER_INFORMATION', - CLEAR_BACKUP: 'CLEAR_BACKUP', - BACKUP_FILE: 'BACKUP_FILE', - SHARE_FILE: 'SHARE_FILE', - CLEAR_DEPARTMENT: 'CLEAR_DEPARTMENT', - DEPARTMENT_FILE: 'DEPARTMENT_FILE', - IS_BACKUP_CREATED: 'IS_BACKUP_CREATED', - GET_BACKUP_STRUCTURE: 'GET_BACKUP_STRUCTURE', - REQ_FILE_FROM_BACKUP: 'REQ_FILE_FROM_BACKUP', - DECRYPT_AND_SAVE_OLD_BACKUP_FILE: 'DECRYPT_AND_SAVE_OLD_BACKUP_FILE', -}; \ No newline at end of file diff --git a/CEO/src/network/operations_base/operation_handler.ts b/CEO/src/network/operations_base/operation_handler.ts deleted file mode 100644 index 4b9a2f2..0000000 --- a/CEO/src/network/operations_base/operation_handler.ts +++ /dev/null @@ -1,57 +0,0 @@ -// operation_handler.ts -import { ParsedMessage, MessageHandler } from '../message_handler'; -import { OperationPlugin } from './operation_plugin'; - -// Define handler function type to return Promise -type OperationHandlerFunction = (parsedMessage: ParsedMessage) => Promise; - -export class OperationHandler { - private static instance: OperationHandler; - private handlers: { [operationCode: string]: OperationHandlerFunction } = {}; - - private constructor() { - this.registerHandler('UNKNOWN_COMMAND', this.handleUnknownCommand); - } - - // Singleton instance - public static getInstance(): OperationHandler { - if (!OperationHandler.instance) { - OperationHandler.instance = new OperationHandler(); - } - return OperationHandler.instance; - } - - // Register a handler for a specific operation code - public registerHandler(operationCode: string, handler: OperationHandlerFunction): void { - this.handlers[operationCode] = handler; - } - - // Handle operation request asynchronously - public async handleOperation(rawMessage: string): Promise { - const parsedMessage = MessageHandler.parseMessage(rawMessage); - if (!parsedMessage || !MessageHandler.validateMessage(parsedMessage)) { - return this.handleUnknownCommand(parsedMessage); - } - - // Retrieve the handler for the operation code and invoke it asynchronously - const handler = this.handlers[parsedMessage.operationCode]; - if (handler) { - return await handler(parsedMessage); - } else { - return this.handleUnknownCommand(parsedMessage); - } - } - - // Default handler for unknown commands - private async handleUnknownCommand(parsedMessage: ParsedMessage): Promise { - return { - operationCode: 'UNKNOWN_COMMAND', - metaInfo: { message: 'Unknown command received.' }, - }; - } - - // Plugin system: Load plugins to register handlers - public loadPlugin(plugin: OperationPlugin): void { - plugin.register(this); - } -} diff --git a/CEO/src/network/operations_base/operation_plugin.ts b/CEO/src/network/operations_base/operation_plugin.ts deleted file mode 100644 index 6b11a29..0000000 --- a/CEO/src/network/operations_base/operation_plugin.ts +++ /dev/null @@ -1,6 +0,0 @@ -// operation_plugin.ts -import { OperationHandler } from './operation_handler'; - -export interface OperationPlugin { - register(operationHandler: OperationHandler): void; -} diff --git a/CEO/src/network/operations_custom/general_operations.ts b/CEO/src/network/operations_custom/general_operations.ts deleted file mode 100644 index afe4c50..0000000 --- a/CEO/src/network/operations_custom/general_operations.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { ParsedMessage } from '../message_handler'; -import { OperationHandler } from '../operations_base/operation_handler'; -import os from 'node:os'; -import {OperationPlugin} from "../operations_base/operation_plugin"; - -export class GeneralOperations implements OperationPlugin { - public static readonly operationCodes = { - OK: 'OK', - ERR: 'ERR', - ARE_YOU_HUMAN: 'ARE_YOU_HUMAN', - ALIVE: 'ALIVE', - SET_PUBLIC_KEY: 'SET_PUBLIC_KEY', - SET_AES_KEY: 'SET_AES_KEY', - }; - - // Handle heartbeat operation asynchronously - public static async handleAreYouHuman(): Promise { - const networkInterfaces = os.networkInterfaces(); - let ipAddress = 'Unknown'; - - for (const iface of Object.values(networkInterfaces)) { - for (const address of iface!) { - if (address.family === 'IPv4' && !address.internal) { - ipAddress = address.address; - break; - } - } - if (ipAddress !== 'Unknown') break; - } - - return { - operationCode: GeneralOperations.operationCodes.ALIVE, - metaInfo: { ipAddress }, - }; - } - - // Handle public key exchange asynchronously - public static async handlePublicKey(parsedMessage: ParsedMessage): Promise { - const clientPublicKey = parsedMessage.metaInfo?.publicKey; - if (clientPublicKey) { - return { - operationCode: GeneralOperations.operationCodes.SET_PUBLIC_KEY, - metaInfo: { publicKey: clientPublicKey }, - }; - } else { - return { - operationCode: GeneralOperations.operationCodes.ERR, - metaInfo: { message: 'No public key provided.' }, - }; - } - } - - // Handle AES key exchange asynchronously - public static async handleAESKey(parsedMessage: ParsedMessage): Promise { - const aesKey = parsedMessage.metaInfo?.aesKey; - const aesIv = parsedMessage.metaInfo?.aesIv; - if (aesKey && aesIv) { - return { - operationCode: GeneralOperations.operationCodes.SET_AES_KEY, - metaInfo: { aesKey, aesIv }, - }; - } else { - return { - operationCode: GeneralOperations.operationCodes.ERR, - metaInfo: { message: 'No AES key provided.' }, - }; - } - } - - // Default async handler for OK operation - public static async handleOk(parsedMessage: ParsedMessage): Promise { - return parsedMessage; // Acknowledge with OK, returning as-is - } - - // Default async handler for ERR operation - public static async handleErr(parsedMessage: ParsedMessage): Promise { - return parsedMessage; // Log the error and return - } - - // Register general operations with the OperationHandler - public register(operationHandler: OperationHandler): void { - operationHandler.registerHandler(GeneralOperations.operationCodes.ARE_YOU_HUMAN, GeneralOperations.handleAreYouHuman); - operationHandler.registerHandler(GeneralOperations.operationCodes.SET_PUBLIC_KEY, GeneralOperations.handlePublicKey); - operationHandler.registerHandler(GeneralOperations.operationCodes.SET_AES_KEY, GeneralOperations.handleAESKey); - operationHandler.registerHandler(GeneralOperations.operationCodes.OK, GeneralOperations.handleOk); - operationHandler.registerHandler(GeneralOperations.operationCodes.ERR, GeneralOperations.handleErr); - } -} diff --git a/CEO/src/network/operations_custom/user_to_user_operations.ts b/CEO/src/network/operations_custom/user_to_user_operations.ts deleted file mode 100644 index 9cc8dec..0000000 --- a/CEO/src/network/operations_custom/user_to_user_operations.ts +++ /dev/null @@ -1,318 +0,0 @@ -import { ParsedMessage } from '../message_handler'; -import { OperationHandler } from '../operations_base/operation_handler'; -import {operationCodes} from "../operation_codes"; -import path from 'path'; -import fs from 'fs/promises'; -import checkDiskSpace from "check-disk-space"; -import { JsonManager } from '../../helpers/json_manager'; -import {OperationPlugin} from "../operations_base/operation_plugin"; - -export class UserToUserOperations implements OperationPlugin { - public static readonly operationCodes = { - SEND_ANNOUNCEMENT: 'SEND_ANNOUNCEMENT', - GET_USER_INFORMATION: 'GET_USER_INFORMATION', - BACKUP_FILE: 'BACKUP_FILE', - CLEAR_BACKUP: 'CLEAR_BACKUP', - SHARE_FILE: 'SHARE_FILE', - CLEAR_DEPARTMENT: 'CLEAR_DEPARTMENT', - DEPARTMENT_FILE: 'DEPARTMENT_FILE', - IS_BACKUP_CREATED: 'IS_BACKUP_CREATED', - GET_BACKUP_STRUCTURE: 'GET_BACKUP_STRUCTURE', - REQ_FILE_FROM_BACKUP: 'REQ_FILE_FROM_BACKUP', - DECRYPT_AND_SAVE_OLD_BACKUP_FILE: 'DECRYPT_AND_SAVE_OLD_BACKUP_FILE', - }; - - private static async hasEnoughDiskSpace(directory: string, requiredPercentage: number = 25): Promise { - try { - const diskInfo = await checkDiskSpace(directory); - const availableSpace = diskInfo.free; - const totalSpace = diskInfo.size; - const availablePercentage = (availableSpace / totalSpace) * 100; - return availablePercentage >= requiredPercentage; - } catch (error) { - console.error(`Error checking disk space: ${error}`); - return false; - } - } - - - public static async handleSendAnnouncement(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.message) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing announcement message.' }}; - } - - const jsonManager = new JsonManager(path.join(__dirname, '..', '..', 'json_files', 'application.json')); - try { - await jsonManager.writeValue('announcement', parsedMessage.metaInfo.message); - console.log(`Announcement saved: ${parsedMessage.metaInfo.message}`); - return { operationCode: operationCodes.OK, metaInfo: { message: 'Announcement saved.' }}; - } catch (error: any) { - console.error(`Error saving announcement: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error: ${error.message}` }}; - } - } - - public static async handleGetUserInformation(parsedMessage: ParsedMessage): Promise { - const jsonManager = new JsonManager(path.join(__dirname, '..', '..', 'json_files', 'userConfig.json')); - try { - const userInfo = await jsonManager.readValue('user_info'); - return { operationCode: operationCodes.OK, metaInfo: userInfo }; - } catch (error: any) { - console.error(`Error fetching user info: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Error fetching user info' }}; - } - } - - public static async handleBackupFile(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.userName || !parsedMessage.metaInfo?.relativeFilePath || !parsedMessage.fileContent) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing file or user information.' }}; - } - - const { userName, relativeFilePath } = parsedMessage.metaInfo; - const fullFilePath = path.join(__dirname, '..', '..', 'backups', userName, relativeFilePath); - - try { - if (!await UserToUserOperations.hasEnoughDiskSpace(path.dirname(fullFilePath), 25)) { - return { operationCode: operationCodes.ERR, metaInfo: - { message: 'Insufficient disk space.' }}; - } - - await fs.mkdir(path.dirname(fullFilePath), { recursive: true }); - await fs.writeFile(fullFilePath, parsedMessage.fileContent as Buffer); - console.log(`File saved: ${fullFilePath}`); - - return { operationCode: operationCodes.OK, metaInfo: { message: `File saved: ${relativeFilePath}` }}; - } catch (error: any) { - console.error(`Error saving file: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error saving file: ${error.message}` }}; - } - } - - public static async handleClearBackup(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.userName) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing user name.' }}; - } - - const userBackupDir = path.join(__dirname, '..', '..', 'backups', parsedMessage.metaInfo.userName); - try { - await fs.rm(userBackupDir, { recursive: true, force: true }); - console.log(`Backup cleared: ${userBackupDir}`); - return { operationCode: operationCodes.OK, metaInfo: { message: `Backup cleared for ${parsedMessage.metaInfo.userName}` }}; - } catch (error: any) { - console.error(`Error clearing backup: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error clearing backup: ${error.message}` }}; - } - } - - public static async handleShareFile(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.userName || !parsedMessage.metaInfo?.relativeFilePath || !parsedMessage.fileContent) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing share info.' }}; - } - - const jsonManager = new JsonManager(path.join(__dirname, '..', '..', 'json_files', 'application.json')); - const { userName, relativeFilePath } = parsedMessage.metaInfo; - - try { - const appInfo = await jsonManager.readValue('shareDirectory'); - const shareDirectory = appInfo?.path || ''; - - console.log(`\n\nShare directory: ${shareDirectory}\n\n`); - - if (!shareDirectory) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Share directory missing.' }}; - } - - const fullFilePath = path.join(shareDirectory, userName, relativeFilePath); - await fs.mkdir(path.dirname(fullFilePath), { recursive: true }); - await fs.writeFile(fullFilePath, parsedMessage.fileContent as Buffer); - console.log(`File shared: ${fullFilePath}`); - - return { operationCode: operationCodes.OK, metaInfo: { message: `File shared: ${relativeFilePath}` }}; - } catch (error: any) { - console.error(`Error sharing file: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error sharing file: ${error.message}` }}; - } - } - - public static async handleClearDepartment(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.userName) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing user name.' }}; - } - - const jsonManager = new JsonManager(path.join(__dirname, '..', '..', 'json_files', 'application.json')); - const { userName } = parsedMessage.metaInfo; - - try { - const appInfo = await jsonManager.readValue('departmentDirectory'); - const departmentDir = appInfo?.path || ''; - const userDepartmentDir = path.join(departmentDir, '..', 'DEPARTMENT_SHARE', userName); - - try { - await fs.access(userDepartmentDir) - }catch(ex: any){ - return { operationCode: operationCodes.OK}; - } - - await fs.rm(userDepartmentDir, { recursive: true, force: true }); - console.log(`Department backup cleared: ${userDepartmentDir}`); - return { operationCode: operationCodes.OK, metaInfo: { message: `Department backup cleared for ${userName}` }}; - } catch (error: any) { - console.error(`Error clearing department: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error clearing department: ${error.message}` }}; - } - } - - public static async handleDepartmentFile(parsedMessage: ParsedMessage): Promise { - // Ensure metaInfo and fileContent are available - if (!parsedMessage.metaInfo || !parsedMessage.fileContent) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: 'Missing file content or meta information.' }, - }; - } - - const { userName, relativeFilePath } = parsedMessage.metaInfo; - - if (!userName || !relativeFilePath) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: 'Missing user name or file path information.' }, - }; - } - - // Path to the application.json to read the shareDirectory field - const pathToApplicationJson = path.join(__dirname, '..', '..', 'json_files', 'application.json'); - const jsonManager = new JsonManager(pathToApplicationJson); - - // Read application configuration asynchronously - let appInfo; - try { - appInfo = await jsonManager.readValue('departmentDirectory'); - } catch (error: any) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: `Error reading application config: ${error.message}` }, - }; - } - - if (!appInfo || !appInfo.path) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: 'Error retrieving department directory from application.json.' }, - }; - } - - // Get the share directory path - const departmentDirectory = appInfo.path; - const fullFilePath = path.join(departmentDirectory, '..', 'DEPARTMENT_FILES', userName, relativeFilePath); - - try { - // Ensure the directory structure exists (create directories if they don't exist) - const dirPath = path.dirname(fullFilePath); - await fs.mkdir(dirPath, { recursive: true }); - - // Write the file content to the specified path - await fs.writeFile(fullFilePath, Buffer.from(parsedMessage.fileContent as Buffer), 'base64'); - - return { - operationCode: operationCodes.OK, - metaInfo: { message: `File shared successfully: ${relativeFilePath}` }, - }; - } catch (error: any) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: `Error sharing file: ${error.message}` }, - }; - } - } - - public static async handleIsBackupCreated(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.name) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing name in meta information.' }}; - } - - const userBackupDir = path.join(__dirname, '..', '..', 'backups', parsedMessage.metaInfo.name); - - try { - const exists = await fs.access(userBackupDir).then(() => true).catch(() => false); - return { operationCode: operationCodes.OK, metaInfo: { backupExists: exists }}; - } catch (error: any) { - console.error(`Error checking backup: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error checking backup: ${error.message}` }}; - } - } - - public static async handleGetBackupStructure(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.name) { - return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing name in meta information.' }}; - } - - const userBackupDir = path.join(__dirname, '..', '..', 'backups', parsedMessage.metaInfo.name); - - try { - const structure = await UserToUserOperations.buildDirectoryStructure(userBackupDir); - return { operationCode: operationCodes.OK, metaInfo: { structure }}; - } catch (error: any) { - console.error(`Error building backup structure: ${error.message}`); - return { operationCode: operationCodes.ERR, metaInfo: { message: `Error: ${error.message}` }}; - } - } - - private static async buildDirectoryStructure(directoryPath: string): Promise { - const structure: any = {}; - const files = await fs.readdir(directoryPath); - - for (const file of files) { - const filePath = path.join(directoryPath, file); - const stats = await fs.stat(filePath); - - if (stats.isDirectory()) { - structure[file] = await UserToUserOperations.buildDirectoryStructure(filePath); - } else { - structure[file] = path.relative(directoryPath, filePath); - } - } - - return structure; - } - - public static async handleReqFileFromBackup(parsedMessage: ParsedMessage): Promise { - if (!parsedMessage.metaInfo?.name || !parsedMessage.metaInfo?.relativeFilePath) { - return { - operationCode: operationCodes.ERR, - metaInfo: { message: 'Missing user name or file path in meta information.' }, - }; - } - - const { name, relativeFilePath } = parsedMessage.metaInfo; - const fullFilePath = path.join(__dirname, '..', '..', 'backups', name, relativeFilePath); - - try { - const fileContent = await fs.readFile(fullFilePath); - return { - operationCode: operationCodes.OK, - metaInfo: { relativeFilePath }, - fileContent, - }; - } catch (error: any) { - console.error(`Error reading file from backup: ${error.message}`); - return { - operationCode: operationCodes.ERR, - metaInfo: { message: `Error reading file: ${error.message}` }, - }; - } - } - - public register(operationHandler: OperationHandler): void { - operationHandler.registerHandler(UserToUserOperations.operationCodes.SEND_ANNOUNCEMENT, UserToUserOperations.handleSendAnnouncement); - operationHandler.registerHandler(UserToUserOperations.operationCodes.GET_USER_INFORMATION, UserToUserOperations.handleGetUserInformation); - operationHandler.registerHandler(UserToUserOperations.operationCodes.BACKUP_FILE, UserToUserOperations.handleBackupFile); - operationHandler.registerHandler(UserToUserOperations.operationCodes.CLEAR_BACKUP, UserToUserOperations.handleClearBackup); - operationHandler.registerHandler(UserToUserOperations.operationCodes.SHARE_FILE, UserToUserOperations.handleShareFile); - operationHandler.registerHandler(UserToUserOperations.operationCodes.CLEAR_DEPARTMENT, UserToUserOperations.handleClearDepartment); - operationHandler.registerHandler(UserToUserOperations.operationCodes.DEPARTMENT_FILE, UserToUserOperations.handleDepartmentFile); - operationHandler.registerHandler(UserToUserOperations.operationCodes.IS_BACKUP_CREATED, UserToUserOperations.handleIsBackupCreated); - operationHandler.registerHandler(UserToUserOperations.operationCodes.GET_BACKUP_STRUCTURE, UserToUserOperations.handleGetBackupStructure); - operationHandler.registerHandler(UserToUserOperations.operationCodes.REQ_FILE_FROM_BACKUP, UserToUserOperations.handleReqFileFromBackup); - } -} diff --git a/CEO/src/network/socket_communicator/socket_communicator_base.ts b/CEO/src/network/socket_communicator/socket_communicator_base.ts deleted file mode 100644 index f749193..0000000 --- a/CEO/src/network/socket_communicator/socket_communicator_base.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { ParsedMessage } from '../message_handler'; -import { OperationHandler } from '../operations_base/operation_handler'; -import { - constants, - createCipheriv, - createDecipheriv, - generateKeyPairSync, - privateEncrypt, - publicDecrypt, - randomBytes -} from "crypto"; - -export abstract class SocketCommunicatorBase { - protected readonly ip: string; - protected readonly port: number; - protected readonly operationHandler: OperationHandler; - protected handlerResult: ParsedMessage | null; - - protected chunkBuffers: { [messageId: string]: string[] }; - - protected privateKey: string | null; - protected publicKey: string | null; - protected aesKey: Buffer | null; - protected aesIv: Buffer | null; - - protected readonly EOP = ''; - protected readonly CHUNK_SIZE = 1024; - private incompleteChunkBuffer: string = ''; - - protected constructor(ip: string, port: number, operationHandler: OperationHandler) { - this.ip = ip; - this.port = port; - this.operationHandler = operationHandler - this.handlerResult = null; - this.chunkBuffers = {}; - - this.privateKey = null; - this.publicKey = null; - this.aesKey = null; - this.aesIv = null; - } - - // Getter for the handler result - getHandlerResult(): ParsedMessage | null { - const result = this.handlerResult; - this.handlerResult = null; - return result; - } - - protected generateKeyPair(): void { - const { privateKey, publicKey } = generateKeyPairSync('rsa', { - modulusLength: 2048, - publicKeyEncoding: { type: 'spki', format: 'pem' }, - privateKeyEncoding: { type: 'pkcs8', format: 'pem' }, - }); - this.privateKey = privateKey; - this.publicKey = publicKey; - } - - protected generateAesKey(): void { - this.aesKey = randomBytes(32); - this.aesIv = randomBytes(16); - } - - protected encryptWithAes(message: string): string { - if (!this.aesKey || !this.aesIv) { - throw new Error('AES key or IV is not set.'); - } - const cipher = createCipheriv('aes-256-cbc', this.aesKey, this.aesIv); - let encrypted = cipher.update(message, 'utf-8'); - encrypted = Buffer.concat([encrypted, cipher.final()]); - return encrypted.toString('base64'); - } - - protected decryptWithAes(encryptedMessage: string): string { - if (!this.aesKey || !this.aesIv) { - throw new Error('AES key or IV is not set.'); - } - const decipher = createDecipheriv('aes-256-cbc', this.aesKey, this.aesIv); - let decrypted = decipher.update(Buffer.from(encryptedMessage, 'base64')); - decrypted = Buffer.concat([decrypted, decipher.final()]); - return decrypted.toString('utf-8'); - } - - protected decryptWithRsa(message: string): string { - if (!this.publicKey) { - throw new Error('Server public key not set.'); - } - try { - const encryptedMessage = Buffer.from(message, 'base64'); - const decrypted = publicDecrypt( - { - key: this.publicKey, - padding: constants.RSA_PKCS1_PADDING, - }, - encryptedMessage - ); - return decrypted.toString('utf-8'); - } catch (error) { - throw new Error('Failed to decrypt RSA message.'); - } - } - - protected encryptWithRsa(message: string): string { - if (!this.privateKey) throw new Error('Server private key not set.'); - return privateEncrypt( - { - key: this.privateKey, - padding: constants.RSA_PKCS1_PADDING, - }, - Buffer.from(message) - ).toString('base64'); - } - - async handleIncomingChunk(data: Buffer): Promise { - // Append incoming data to the incomplete buffer - this.incompleteChunkBuffer += data.toString(); - - // Split the buffer by to separate complete and incomplete messages - const messages = this.incompleteChunkBuffer.split(this.EOP); - - // Save the last item back to the buffer if it's incomplete (no at the end) - this.incompleteChunkBuffer = messages.pop() || ""; - - // Process each complete message in the split results - for (const incomingMessage of messages) { - try { - const [headerJson, chunkContent] = incomingMessage.split('|'); - const header = JSON.parse(headerJson); - - // Initialize an array for chunks if it's the first chunk for this messageId - if (!this.chunkBuffers[header.messageId]) { - this.chunkBuffers[header.messageId] = []; - } - - // Store the chunk in the correct position based on sequenceNumber (1-based indexing) - this.chunkBuffers[header.messageId][header.sequenceNumber - 1] = chunkContent; - - // Check if all chunks have been received - if (this.chunkBuffers[header.messageId].filter(chunk => chunk !== undefined).length === header.totalChunks) { - // Join all chunks to form the full message - const fullMessage = this.chunkBuffers[header.messageId].join(''); - - // Process the complete message - await this.handleIncomingMessage(fullMessage); - - // Clear the chunk buffer for this messageId - delete this.chunkBuffers[header.messageId]; - } - } catch (error: any) { - console.error(`Error handling chunk: ${error.message}`); - } - } - } - - abstract handleIncomingMessage(incomingMessage: string): Promise; - - abstract sendMessage(message: string): Promise; -} diff --git a/CEO/src/network/socket_communicator/tcp_client_communicator.ts b/CEO/src/network/socket_communicator/tcp_client_communicator.ts deleted file mode 100644 index 11824b8..0000000 --- a/CEO/src/network/socket_communicator/tcp_client_communicator.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Socket } from 'net'; -import { SocketCommunicatorBase } from './socket_communicator_base'; -import { OperationHandler } from '../operations_base/operation_handler'; -import { operationCodes } from '../operation_codes'; -import {MessageHandler} from "../message_handler"; - -export class TcpClientCommunicator extends SocketCommunicatorBase { - private readonly socket: Socket; - private isAesKeySetFlag: boolean; - - constructor(socket: Socket, ip: string, port: number, operationHandler: OperationHandler) { - super(ip, port, operationHandler); - this.socket = socket; - this.aesKey = null; - this.aesIv = null; - this.isAesKeySetFlag = false; - this.chunkBuffers = {}; - } - - isAesKeySet(): boolean { - return this.isAesKeySetFlag; - } - - setServerPublicKey(publicKey: string): void { - this.publicKey = publicKey; - } - - setAesKey(aesKey: string, aesIv: string): void { - this.aesKey = Buffer.from(aesKey, 'base64'); - this.aesIv = Buffer.from(aesIv, 'base64'); - } - - async handleIncomingMessage(incomingMessage: string): Promise { - let messageToProcess; - - if (this.aesKey && this.aesIv) { - messageToProcess = this.decryptWithAes(incomingMessage); - } else if (this.publicKey) { - messageToProcess = this.decryptWithRsa(incomingMessage); - } else { - messageToProcess = Buffer.from(incomingMessage, 'base64').toString('utf-8'); - } - - const result = await this.operationHandler.handleOperation(messageToProcess); - - if (result.operationCode === operationCodes.SET_AES_KEY) { - this.isAesKeySetFlag = true; - this.setAesKey(result.metaInfo?.aesKey, result.metaInfo?.aesIv); - return; - } - - if (result.operationCode === operationCodes.SET_PUBLIC_KEY) { - this.setServerPublicKey(result.metaInfo?.publicKey); - return; - } - - this.handlerResult = result; - } - - async sendMessage(operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer): Promise { - const message = MessageHandler.formatMessage(operationCode, metaInfo, fileContent); - - const outgoingMessage = this.encryptWithAes(message); - - // Calculate optimal chunk size based on network latency - const totalChunks = Math.ceil(outgoingMessage.length / this.CHUNK_SIZE); - - const messageId = Date.now().toString(); - - // Send each chunk with a delay between them - for (let i = 0; i < totalChunks; i++) { - const chunk = outgoingMessage.slice(i * this.CHUNK_SIZE, (i + 1) * this.CHUNK_SIZE); - const chunkHeader = JSON.stringify({ - messageId, - sequenceNumber: i + 1, - totalChunks, - }); - const chunkWithHeader = `${chunkHeader}|${chunk}${this.EOP}`; - - if (!this.socket.write(chunkWithHeader)) { - // Wait for the 'drain' event before writing the next chunk - await new Promise((resolve) => this.socket.once('drain', resolve)); - } - } - } - -} diff --git a/CEO/src/network/socket_communicator/tcp_server_communicator.ts b/CEO/src/network/socket_communicator/tcp_server_communicator.ts deleted file mode 100644 index aa1779b..0000000 --- a/CEO/src/network/socket_communicator/tcp_server_communicator.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Socket } from 'net'; -import { MessageHandler } from '../message_handler'; -import { SocketCommunicatorBase } from './socket_communicator_base'; -import { OperationHandler } from '../operations_base/operation_handler'; -import {operationCodes} from "../operation_codes"; - -export class TcpServerCommunicator extends SocketCommunicatorBase { - private readonly socket: Socket; - - constructor(socket: Socket, ip: string, port: number, operationHandler: OperationHandler) { - super(ip, port, operationHandler); - this.socket = socket; - } - - async sendPublicKey(): Promise { - this.generateKeyPair(); - if (!this.publicKey || !this.privateKey) { - throw new Error('RSA key pair is not available. Please generate RSA key pair.'); - } - - await this.sendMessage(operationCodes.SET_PUBLIC_KEY, { publicKey: this.publicKey }); - } - - async sendAesKey(): Promise { - this.generateAesKey(); - if (!this.aesKey || !this.aesIv) { - throw new Error('AES key or IV is not available. Please generate AES key.'); - } - - const aesKeyBase64 = this.aesKey.toString('base64'); - const aesIvBase64 = this.aesIv.toString('base64'); - await this.sendMessage(operationCodes.SET_AES_KEY, { aesKey: aesKeyBase64, aesIv: aesIvBase64 }); - } - - async handleIncomingMessage(incomingMessage: string): Promise { - const messageToProcess = this.decryptWithAes(incomingMessage); - this.handlerResult = await this.operationHandler.handleOperation(messageToProcess); - } - - async sendMessage(operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer): Promise { - const message = MessageHandler.formatMessage(operationCode, metaInfo, fileContent); - - let outgoingMessage: string; - switch (operationCode) { - case operationCodes.SET_PUBLIC_KEY: - outgoingMessage = Buffer.from(message, 'utf-8').toString('base64'); - break; - case operationCodes.SET_AES_KEY: - outgoingMessage = this.encryptWithRsa(message); - break; - default: - outgoingMessage = this.encryptWithAes(message); - } - - const totalChunks = Math.ceil(outgoingMessage.length / this.CHUNK_SIZE); - const messageId = Date.now().toString(); - - // Send each chunk with a delay between them - for (let i = 0; i < totalChunks; i++) { - const chunk = outgoingMessage.slice(i * this.CHUNK_SIZE, (i + 1) * this.CHUNK_SIZE); - const chunkHeader = JSON.stringify({ - messageId, - sequenceNumber: i + 1, - totalChunks, - }); - const chunkWithHeader = `${chunkHeader}|${chunk}${this.EOP}`; - - if (!this.socket.write(chunkWithHeader)) { - // Wait for the 'drain' event before writing the next chunk - await new Promise((resolve) => this.socket.once('drain', resolve)); - } - } - } -} diff --git a/CEO/src/network/socket_communicator/udp_socket_communicator.ts b/CEO/src/network/socket_communicator/udp_socket_communicator.ts deleted file mode 100644 index f9f4e48..0000000 --- a/CEO/src/network/socket_communicator/udp_socket_communicator.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Socket as UdpSocket } from 'dgram'; -import { MessageHandler } from '../message_handler'; -import { SocketCommunicatorBase } from './socket_communicator_base'; -import {OperationHandler} from "../operations_base/operation_handler"; - -export class UdpSocketCommunicator extends SocketCommunicatorBase { - private readonly socket: UdpSocket; - - constructor(socket: UdpSocket, ip: string, port: number, operationHandler: OperationHandler) { - super(ip, port, operationHandler); - this.socket = socket; - } - - // Send plain message over UDP (metaInfo as JSON and fileContent as Buffer) - async sendMessage(operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer): Promise { - const message = MessageHandler.formatMessage(operationCode, metaInfo, fileContent); - return new Promise((resolve, reject) => { - this.socket.send(message, this.port, this.ip, (err: any) => { - if (err) { - console.error('Error sending UDP message:', err); - return reject(err); - } - console.log(`Plain message sent to ${this.ip}:${this.port} (UDP)`); - resolve(); - }); - }); - } - - // Handle incoming message (no decryption needed for UDP) - async handleIncomingMessage(incomingMessage: string): Promise { - this.handlerResult = await this.operationHandler.handleOperation(incomingMessage); - } -} diff --git a/CEO/src/network/tcp/tcp_client.ts b/CEO/src/network/tcp/tcp_client.ts deleted file mode 100644 index e87efae..0000000 --- a/CEO/src/network/tcp/tcp_client.ts +++ /dev/null @@ -1,111 +0,0 @@ -import net, { Socket } from 'net'; -import { TcpClientCommunicator } from '../socket_communicator/tcp_client_communicator'; -import { OperationHandler } from '../operations_base/operation_handler'; -import { operationCodes } from "../operation_codes"; -import { GeneralOperations } from "../operations_custom/general_operations"; -import { UserToUserOperations } from "../operations_custom/user_to_user_operations"; -import { ParsedMessage } from "../message_handler"; - -export class TcpClient { - private readonly tcp_port: number; - private socket: Socket | null; - private communicator: TcpClientCommunicator | null; - private readonly operationHandler: OperationHandler; - private lastResult: ParsedMessage | null; - - constructor(tcp_port: number) { - this.tcp_port = tcp_port; - this.socket = null; - this.communicator = null; - this.operationHandler = OperationHandler.getInstance(); - this.lastResult = null; - - this.operationHandler.loadPlugin(new GeneralOperations()); - this.operationHandler.loadPlugin(new UserToUserOperations()); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[TcpClient]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - // Open a TCP socket connection - openSocket(ip: string): void { - this.socket = new net.Socket(); - - this.socket.connect(this.tcp_port, ip, () => { - this.log(`Connected to server at ${ip}:${this.tcp_port}`); - this.communicator = new TcpClientCommunicator(this.socket as Socket, ip, this.tcp_port, this.operationHandler); - }); - - this.socket.on('error', (err) => { - this.log(`Connection error to server at ${ip}:${this.tcp_port}: ${err.message}`, 'error'); - }); - - this.socket.on('data', async (data: Buffer) => { - if (this.communicator) { - await this.communicator.handleIncomingChunk(data); - this.lastResult = this.communicator.getHandlerResult(); - this.log(`Data received from ${ip}:${this.tcp_port}`); - } - }); - - this.socket.on('close', () => { - this.log(`Connection closed: ${ip}:${this.tcp_port}`); - this.lastResult = null; - }); - } - - // Close the socket connection - closeSocket(): void { - if (this.socket) { - this.socket.end(); - this.socket = null; - this.communicator = null; - this.lastResult = null; - this.log('Client socket connection closed.'); - } - } - - // Send a message with operationCode, metaInfo, and fileContent in chunks - async sendMessage(operationCode: string, metaInfo?: { [key: string]: any }, fileContent?: Buffer): Promise { - if (!this.communicator || !this.isAesKeySet()) { - this.log('Communicator not initialized or AES key not set.', 'error'); - return false; - } - - this.log(`Sending message with operationCode: ${operationCode}`); - await this.communicator.sendMessage(operationCode, metaInfo, fileContent); - return true; - } - - // Check if AES key is set - isAesKeySet(): boolean { - if (!this.communicator) return false; - return this.communicator?.isAesKeySet(); - } - - // Check if the message is received (based on if lastResult is available) - isMessageReceived(): boolean { - return this.lastResult !== null; - } - - // Get the last result (and clear it after returning) - getLastResult(): ParsedMessage | null { - const result = this.lastResult; - this.lastResult = null; - return result; - } - - // Check if the socket is still connected - isSocketConnected(): boolean { - const connected = this.socket !== null && !this.socket.destroyed; - this.log(`Socket connected: ${connected}`); - return connected; - } -} diff --git a/CEO/src/network/tcp/tcp_server.ts b/CEO/src/network/tcp/tcp_server.ts deleted file mode 100644 index 6e3429f..0000000 --- a/CEO/src/network/tcp/tcp_server.ts +++ /dev/null @@ -1,119 +0,0 @@ -import net, { Socket } from 'net'; -import path from 'path'; -import dotenv from 'dotenv'; -import { ConnectionManager } from "../connection_manager"; -import { TcpServerCommunicator } from "../socket_communicator/tcp_server_communicator"; -import { GeneralOperations } from "../operations_custom/general_operations"; -import { OperationHandler } from "../operations_base/operation_handler"; -import { UserToUserOperations } from "../operations_custom/user_to_user_operations"; - -dotenv.config({ path: path.resolve(__dirname, './config/.env') }); - -export class TcpServer { - private readonly connectionManager: ConnectionManager; - private readonly operationHandler: OperationHandler; - private readonly port: number; - private readonly host: string; - private clientQueues: Map> = new Map(); - - constructor(host: string, port: number) { - this.connectionManager = new ConnectionManager(); - this.operationHandler = OperationHandler.getInstance(); - this.host = host; - this.port = port; - - this.operationHandler.loadPlugin(new GeneralOperations()); - this.operationHandler.loadPlugin(new UserToUserOperations()); - } - - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[TcpServer]'; - console[level === 'error' ? 'error' : 'log'](`${prefix} ${message}`); - } - - public start(): void { - const tcpServer = net.createServer(); - - tcpServer.on('connection', (socket: Socket) => { - const ip = socket.remoteAddress || 'unknown'; - const port = socket.remotePort || 0; - const clientId = `${ip}:${port}`; - - this.log(`Client connected: ${clientId}`); - - const tcpCommunicator = new TcpServerCommunicator(socket, ip, port, this.operationHandler); - this.connectionManager.addConnection(ip, port, tcpCommunicator); - - tcpCommunicator.sendPublicKey() - .then(() => tcpCommunicator.sendAesKey()) - .catch(err => { - this.log(`Error during key exchange with client ${clientId}: ${err}`, 'error'); - socket.end(); - }); - - this.clientQueues.set(clientId, Promise.resolve()); - - socket.on('data', (data: Buffer) => { - this.queueClientDataProcessing(data, ip, port); - }); - - socket.on('end', () => { - this.log(`Client disconnected: ${clientId}`); - this.connectionManager.removeCommunicator(ip, port); - this.clientQueues.delete(clientId); - }); - - socket.on('error', (err: Error) => { - this.log(`Error from client ${clientId}: ${err.message}`, 'error'); - this.connectionManager.removeCommunicator(ip, port); - this.clientQueues.delete(clientId); - }); - }); - - tcpServer.on('error', (err: Error) => { - this.log(`TCP server error: ${err.message}`, 'error'); - }); - - tcpServer.listen(this.port, this.host, () => { - this.log(`TCP server listening on ${this.host}:${this.port}`); - }); - } - - private queueClientDataProcessing(data: Buffer, ip: string, port: number): void { - const clientId = `${ip}:${port}`; - const clientQueue = this.clientQueues.get(clientId) || Promise.resolve(); - - this.clientQueues.set( - clientId, - clientQueue.then(() => this.handleData(data, ip, port)).catch(error => { - this.log(`Error handling data for ${clientId}: ${error}`, 'error'); - }) - ); - } - - private async handleData(data: Buffer, ip: string, port: number): Promise { - const clientId = `${ip}:${port}`; - const communicator = this.connectionManager.getCommunicator(ip, port) as TcpServerCommunicator; - if (!communicator) { - this.log(`No communicator found for ${clientId}`, 'error'); - return; - } - - await communicator.handleIncomingChunk(data); - - // Check if message is complete before fetching result - const handlerResult = communicator.getHandlerResult(); - if (handlerResult) { - try { - await communicator.sendMessage( - handlerResult.operationCode, - handlerResult.metaInfo, - handlerResult.fileContent - ); - this.log(`Response sent to ${clientId}`); - } catch (err) { - this.log(`Failed to send response to ${clientId}: ${err}`, 'error'); - } - } - } -} diff --git a/CEO/src/network/udp/udp_client.ts b/CEO/src/network/udp/udp_client.ts deleted file mode 100644 index a16c2e1..0000000 --- a/CEO/src/network/udp/udp_client.ts +++ /dev/null @@ -1,161 +0,0 @@ -import dgram from 'dgram'; -import ping from 'ping'; -import { OperationHandler } from '../operations_base/operation_handler'; -import { MessageHandler } from '../message_handler'; -import { GeneralOperations } from "../operations_custom/general_operations"; -import { operationCodes } from "../operation_codes"; -import os from 'os'; - -export class UdpClient { - private udpSocket: dgram.Socket; - private readonly port: number; - private operationHandler: OperationHandler; - - constructor(port: number) { - this.port = port; - this.udpSocket = dgram.createSocket('udp4'); - this.operationHandler = OperationHandler.getInstance(); - this.operationHandler.loadPlugin(new GeneralOperations()); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[UdpClient]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - // Send heartbeat and get clients that respond with ALIVE, excluding the host machine's IP addresses - async getTargetClients(heartbeatCode: string): Promise { - const subnet = this.getSubnet(); - const ipRange = this.getIPRange(subnet); - - // Get local machine's IP addresses to exclude - const localIPs = this.getLocalIPs(); - this.log(`Local IPs to exclude from scan: ${localIPs.join(', ')}`); - - // First, filter active IPs that respond to ping - const activeIps = await this.filterActiveIps(ipRange); - this.log(`Active IPs in subnet ${subnet}: ${activeIps.join(', ')}`); - - // Send heartbeat to each active IP and keep only those that respond with ALIVE - const aliveClients: string[] = []; - for (const ip of activeIps) { - if (!localIPs.includes(ip)) { - const result = await this.sendHeartbeat(ip, heartbeatCode); - if (result.found) { - aliveClients.push(ip); - } - } - } - - this.log(`Alive clients (excluding local machine): ${aliveClients.join(', ')}`); - return aliveClients; - } - - // Get local IP addresses of the host machine (excluding loopback) - private getLocalIPs(): string[] { - const interfaces = os.networkInterfaces(); - const localIPs: string[] = []; - - Object.values(interfaces).forEach((iface) => { - iface?.forEach((address) => { - if (address.family === 'IPv4' && !address.internal) { - localIPs.push(address.address); - } - }); - }); - - return localIPs; - } - - // Send heartbeat to an IP - private async sendHeartbeat(ip: string, heartbeatCode: string): Promise<{ found: boolean }> { - return new Promise((resolve) => { - const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode); - - this.log(`Sending heartbeat to ${ip}`); - this.udpSocket.send(heartbeatMessage, this.port, ip, (err) => { - if (err) { - this.log(`Failed to send heartbeat to ${ip}: ${err.message}`, 'error'); - resolve({ found: false }); - } else { - const timeout = setTimeout(() => { - this.dropConnection(ip); - resolve({ found: false }); - }, 1500); - - this.udpSocket.once('message', (msg, rinfo) => { - if (rinfo.address === ip) { - clearTimeout(timeout); - const parsedMessage = MessageHandler.parseMessage(msg.toString()); - if (parsedMessage?.operationCode === operationCodes.ALIVE) { - this.log(`Received ALIVE response from ${ip}`); - resolve({ found: true }); - } else { - this.log(`Unexpected response from ${ip}`); - resolve({ found: false }); - } - } - }); - } - }); - }); - } - - // Drop connection for a specific IP - private dropConnection(ip: string): void { - try { - this.udpSocket.removeAllListeners('message'); - this.log(`Dropped connection listeners for ${ip}`); - } catch (err: any) { - this.log(`Error dropping connection to ${ip}: ${err.message}`, 'error'); - } - } - - // Get the subnet (e.g., 192.168.1) - private getSubnet(): string { - const interfaces = os.networkInterfaces(); - for (const iface of Object.values(interfaces)) { - for (const address of iface || []) { - if (address.family === 'IPv4' && !address.internal) { - const subnet = address.address.split('.').slice(0, 3).join('.'); - this.log(`Detected subnet: ${subnet}`); - return subnet; - } - } - } - return ''; - } - - // Get IP range (assuming /24 subnet) - private getIPRange(subnet: string): string[] { - const ipRange = []; - for (let i = 1; i < 255; i++) { - ipRange.push(`${subnet}.${i}`); - } - this.log(`Generated IP range for subnet ${subnet}`); - return ipRange; - } - - // Filter only active IPs by pinging each IP in the range - private async filterActiveIps(ipRange: string[]): Promise { - const activeIps: string[] = []; - - const pingPromises = ipRange.map(ip => ping.promise.probe(ip, { timeout: 1 })); - - const pingResults = await Promise.all(pingPromises); - - for (const result of pingResults) { - if (result.alive) { - activeIps.push(result.host); - } - } - - this.log(`Active IPs after pinging: ${activeIps.join(', ')}`); - return activeIps; - } -} diff --git a/CEO/src/network/udp/udp_server.ts b/CEO/src/network/udp/udp_server.ts deleted file mode 100644 index c18aaa5..0000000 --- a/CEO/src/network/udp/udp_server.ts +++ /dev/null @@ -1,77 +0,0 @@ -import dgram, { RemoteInfo } from 'dgram'; -import { UdpSocketCommunicator } from "../socket_communicator/udp_socket_communicator"; -import { OperationHandler } from "../operations_base/operation_handler"; -import { GeneralOperations } from "../operations_custom/general_operations"; - -export class UdpServer { - private readonly udpServer: dgram.Socket; - private readonly operationHandler: OperationHandler; - private readonly port: number; - private readonly host: string; - - constructor(host: string, port: number) { - this.udpServer = dgram.createSocket('udp4'); - this.operationHandler = OperationHandler.getInstance(); - this.host = host; - this.port = port; - - // Load only the GeneralOperations into the operation handler - this.operationHandler.loadPlugin(new GeneralOperations()); - } - - // Unified logging function - private log(message: string, level: 'log' | 'error' = 'log'): void { - const prefix = '[UdpServer]'; - if (level === 'error') { - console.error(`${prefix} ${message}`); - } else { - console.log(`${prefix} ${message}`); - } - } - - // Start the UDP server - public start(): void { - this.udpServer.on('message', this.handleUdpMessages.bind(this)); - this.udpServer.on('error', this.handleError.bind(this)); - this.udpServer.on('listening', this.handleListening.bind(this)); - - // Bind the server to the UDP port and host - this.udpServer.bind(this.port, this.host); - } - - // Handle incoming UDP messages - private async handleUdpMessages(msg: Buffer, rinfo: RemoteInfo): Promise { - const ip = rinfo.address; - const port = rinfo.port; - - this.log(`Received message from ${ip}:${port}`); - - // Create a temporary communicator for the incoming message - const communicator = new UdpSocketCommunicator(this.udpServer, ip, port, this.operationHandler); - - // Process the incoming message using the communicator - await communicator.handleIncomingMessage(msg.toString()); - - const communicatorResult = communicator.getHandlerResult(); - if (communicatorResult) { - // Send response back to the client using the temporary communicator - try { - await communicator.sendMessage(communicatorResult.operationCode, communicatorResult.metaInfo); - this.log(`Sent response to ${ip}:${port}`); - } catch (error: any) { - this.log(`Error sending response to ${ip}:${port}: ${error.message}`, 'error'); - } - } - } - - // Handle UDP server errors - private handleError(err: Error): void { - this.log(`UDP server error:\n${err.stack}`, 'error'); - } - - // Handle when the UDP server starts listening - private handleListening(): void { - const address = this.udpServer.address(); - this.log(`UDP server listening on ${address.address}:${address.port}`); - } -} diff --git a/CEO/src/workers/backup_retrieval_worker.ts b/CEO/src/workers/backup_retrieval_worker.ts deleted file mode 100644 index ef1a3dd..0000000 --- a/CEO/src/workers/backup_retrieval_worker.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { BackupRetrievalWorker } from '../helpers/backup_retrieval'; -import dotenv from 'dotenv'; - -// Load environment variables from .env file if it exists -dotenv.config(); - -// Retrieve configuration from environment variables -const userConfigPath = process.env.USER_CONFIG_PATH as string; -const applicationInfoPath = process.env.APPLICATION_INFO_PATH as string; -const clientPort = Number(process.env.CLIENT_PORT); -const destinationPath = process.env.DESTINATION_PATH as string; - -// Validate that all required environment variables are present -if (!userConfigPath || !applicationInfoPath || !clientPort || !destinationPath) { - console.error('Error: Missing required environment variables.'); - process.exit(1); -} - -// Initialize the BackupRetrievalWorker -const backupRetrievalWorker = new BackupRetrievalWorker( - userConfigPath, - applicationInfoPath, - clientPort, - destinationPath -); - -// Start the backup retrieval process -backupRetrievalWorker.start().then(() => { - console.log('Backup retrieval process completed successfully.'); -}); - -process.on('SIGTERM', async () => { - console.log('Received SIGTERM. Cleaning up...'); - await cleanupAndExit(); -}); - -process.on('SIGINT', async () => { - console.log('Received SIGINT. Cleaning up...'); - await cleanupAndExit(); -}); - -async function cleanupAndExit() { - // Perform any cleanup, such as closing connections, saving data, etc. - // Example: if you have a server instance running, you may want to close it: - // await server.close(); - - console.log('Cleanup complete. Exiting.'); - process.exit(0); // Exit with code 0 to indicate a clean exit -} - diff --git a/CEO/src/workers/directories_watcher_worker.ts b/CEO/src/workers/directories_watcher_worker.ts deleted file mode 100644 index b864f40..0000000 --- a/CEO/src/workers/directories_watcher_worker.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { DirectoryWatcher } from "../helpers/directory_watcher"; -import dotenv from 'dotenv'; - -// Load environment variables from .env file if it exists -dotenv.config(); - -// Retrieve configuration from environment variables -const memoryManagerPath = process.env.MEMORY_MANAGER_PATH as string; -const applicationInfoPath = process.env.APPLICATION_INFO_PATH as string; - -// Validate that all required environment variables are present -if (!memoryManagerPath || !applicationInfoPath) { - console.error('Error: Missing required environment variables.'); - process.exit(1); -} - -// Initialize and start DirectoryWatcher instances -const backupDirectoryManager = new DirectoryWatcher(memoryManagerPath, applicationInfoPath, 'backupDirectory'); -backupDirectoryManager.start(); - -const departmentShareManager = new DirectoryWatcher(memoryManagerPath, applicationInfoPath, 'departmentDirectory'); -departmentShareManager.start(); - -const shareFileManager = new DirectoryWatcher(memoryManagerPath, applicationInfoPath, 'shareDirectory'); -shareFileManager.start(); - -process.on('SIGTERM', async () => { - console.log('Received SIGTERM. Cleaning up...'); - await cleanupAndExit(); -}); - -process.on('SIGINT', async () => { - console.log('Received SIGINT. Cleaning up...'); - await cleanupAndExit(); -}); - -async function cleanupAndExit() { - backupDirectoryManager.closeWatcher(); - departmentShareManager.closeWatcher(); - shareFileManager.closeWatcher(); - - console.log('Cleanup complete. Exiting.'); - process.exit(0); // Exit with code 0 to indicate a clean exit -} diff --git a/CEO/src/workers/network_scanner_worker.ts b/CEO/src/workers/network_scanner_worker.ts deleted file mode 100644 index f60bf03..0000000 --- a/CEO/src/workers/network_scanner_worker.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { parentPort } from 'worker_threads'; -import { NetworkScanner } from '../helpers/network_scanner'; - -// Extract data from environment variables -const udpPort = parseInt(process.env.UDP_PORT || '0', 10); -const tcpPort = parseInt(process.env.TCP_PORT || '0', 10); -const okPage = process.env.OK_PAGE || ''; -const errorPage = process.env.ERROR_PAGE || ''; -const databaseResetPage = process.env.DATABASE_RESET_PAGE || ''; -const userConfigPath = process.env.USER_CONFIG_PATH || ''; -const applicationInfoPath = process.env.APPLICATION_INFO_PATH || ''; - -// Start the NetworkScanner instance -const networkScanner = new NetworkScanner( - applicationInfoPath, - userConfigPath, - udpPort, - tcpPort, - okPage, - errorPage, - databaseResetPage -); - -process.on('SIGTERM', async () => { - console.log('Received SIGTERM. Cleaning up...'); - await cleanupAndExit(); -}); - -process.on('SIGINT', async () => { - console.log('Received SIGINT. Cleaning up...'); - await cleanupAndExit(); -}); - -async function cleanupAndExit() { - networkScanner.stopAllIntervals(); - - console.log('Cleanup complete. Exiting.'); - process.exit(0); // Exit with code 0 to indicate a clean exit -} diff --git a/CEO/src/workers/resource_coordinator_worker.ts b/CEO/src/workers/resource_coordinator_worker.ts deleted file mode 100644 index c10513c..0000000 --- a/CEO/src/workers/resource_coordinator_worker.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { UsersInfoFetcher } from '../helpers/users_info_fetcher'; -import { BackupManager } from '../helpers/backup_manager'; -import { FileSharer } from '../helpers/file_sharer'; -import { DepartmentSharer } from '../helpers/department_sharer'; - -// Retrieve data from environment variables -const usersConfigPath = process.env.USERS_CONFIG_PATH || ''; -const applicationInfoPath = process.env.APPLICATION_INFO_PATH || ''; -const memoryManagerPath = process.env.MEMORY_MANAGER_PATH || ''; -const queueManagerPath = process.env.QUEUE_MANAGER_PATH || ''; -const tcpPort = parseInt(process.env.TCP_PORT || '0', 10); - -const usersInfoFetcher = new UsersInfoFetcher(applicationInfoPath, memoryManagerPath, tcpPort); -usersInfoFetcher.start(); - -const backupManager = new BackupManager(usersConfigPath, applicationInfoPath, memoryManagerPath, tcpPort); -backupManager.start(); - -const fileSharer = new FileSharer(queueManagerPath, tcpPort); -fileSharer.start(); - -const departmentSharer = new DepartmentSharer(usersConfigPath, applicationInfoPath, memoryManagerPath, tcpPort); -departmentSharer.start(); - -process.on('SIGTERM', async () => { - console.log('Received SIGTERM. Cleaning up...'); - await cleanupAndExit(); -}); - -process.on('SIGINT', async () => { - console.log('Received SIGINT. Cleaning up...'); - await cleanupAndExit(); -}); - -async function cleanupAndExit() { - usersInfoFetcher.stop(); - await backupManager.stop(); - await fileSharer.stop(); - await departmentSharer.stop(); - - console.log('Cleanup complete. Exiting.'); - process.exit(0); // Exit with code 0 to indicate a clean exit -} diff --git a/CEO/src/workers/send_announcement_worker.ts b/CEO/src/workers/send_announcement_worker.ts deleted file mode 100644 index 2d772f2..0000000 --- a/CEO/src/workers/send_announcement_worker.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { AnnouncementSender } from "../helpers/announcement_sender"; - -// Read environment variables passed by WorkerManager -const applicationInfoPath = process.env.APPLICATION_INFO_PATH as string; -const clientPort = parseInt(process.env.CLIENT_PORT as string, 10); -const message = process.env.MESSAGE as string; - -if (!applicationInfoPath || !clientPort || !message) { - console.error("Missing necessary environment variables for AnnouncementWorker."); - process.exit(1); -} - -// Initialize the AnnouncementSender instance -const announcementSender = new AnnouncementSender(applicationInfoPath, clientPort); - -// Start the announcement process -announcementSender.start(message); - -// Handle graceful termination on receiving kill signals -const handleExit = async () => { - console.log("Announcement worker is shutting down gracefully..."); - await announcementSender.stop(); // Assuming stop() is implemented to clean up resources - process.exit(0); -}; - -process.on('SIGTERM', handleExit); -process.on('SIGINT', handleExit); diff --git a/CEO/src/workers/servers_worker.ts b/CEO/src/workers/servers_worker.ts deleted file mode 100644 index 1555807..0000000 --- a/CEO/src/workers/servers_worker.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { UdpServer } from "../network/udp/udp_server"; -import { TcpServer } from "../network/tcp/tcp_server"; - -let udpServer: UdpServer | null -let tcpServer: TcpServer | null - -// Retrieve data from environment variables -const USER_UDP_PORT = parseInt(process.env.USER_UDP_PORT || '0', 10); -const USER_TCP_PORT = parseInt(process.env.USER_TCP_PORT || '0', 10); -const HOST = process.env.HOST || ''; - -// Initialize and start the servers -udpServer = new UdpServer(HOST, USER_UDP_PORT); -udpServer.start(); - -tcpServer = new TcpServer(HOST, USER_TCP_PORT); -tcpServer.start(); - -process.on('SIGTERM', async () => { - console.log('Received SIGTERM. Cleaning up...'); - await cleanupAndExit(); -}); - -process.on('SIGINT', async () => { - console.log('Received SIGINT. Cleaning up...'); - await cleanupAndExit(); -}); - -async function cleanupAndExit() { - // Perform any cleanup, such as closing connections, saving data, etc. - // Example: if you have a server instance running, you may want to close it: - // await server.close(); - - console.log('Cleanup complete. Exiting.'); - process.exit(0); // Exit with code 0 to indicate a clean exit -} diff --git a/CEO/tsconfig.json b/CEO/tsconfig.json deleted file mode 100644 index a62789c..0000000 --- a/CEO/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./dist", - "module": "commonjs", - "target": "es6", - "sourceMap": true, - "strict": true, - "esModuleInterop": true, - "moduleResolution": "node" - }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules" - ] -} diff --git a/CEO/.env b/Desktop App/.env similarity index 68% rename from CEO/.env rename to Desktop App/.env index c411426..1ea3d4a 100644 --- a/CEO/.env +++ b/Desktop App/.env @@ -1,4 +1,3 @@ UDP_PORT=41234 TCP_PORT=41233 - -HOST=0.0.0.0 \ No newline at end of file +IS_CLIENT=true \ No newline at end of file diff --git a/User/.prettierignore b/Desktop App/.prettierignore similarity index 100% rename from User/.prettierignore rename to Desktop App/.prettierignore diff --git a/User/.prettierrc b/Desktop App/.prettierrc similarity index 100% rename from User/.prettierrc rename to Desktop App/.prettierrc diff --git a/User/package-lock.json b/Desktop App/package-lock.json similarity index 100% rename from User/package-lock.json rename to Desktop App/package-lock.json diff --git a/User/package.json b/Desktop App/package.json similarity index 100% rename from User/package.json rename to Desktop App/package.json diff --git a/CEO/render/assets/2581896.png b/Desktop App/render/ceo/assets/2581896.png similarity index 100% rename from CEO/render/assets/2581896.png rename to Desktop App/render/ceo/assets/2581896.png diff --git a/CEO/render/assets/cloud-computing.webp b/Desktop App/render/ceo/assets/cloud-computing.webp similarity index 100% rename from CEO/render/assets/cloud-computing.webp rename to Desktop App/render/ceo/assets/cloud-computing.webp diff --git a/CEO/render/assets/hard-disk.ico b/Desktop App/render/ceo/assets/hard-disk.ico similarity index 100% rename from CEO/render/assets/hard-disk.ico rename to Desktop App/render/ceo/assets/hard-disk.ico diff --git a/CEO/render/assets/mail_2772213.png b/Desktop App/render/ceo/assets/mail_2772213.png similarity index 100% rename from CEO/render/assets/mail_2772213.png rename to Desktop App/render/ceo/assets/mail_2772213.png diff --git a/CEO/render/assets/refresh-data.webp b/Desktop App/render/ceo/assets/refresh-data.webp similarity index 100% rename from CEO/render/assets/refresh-data.webp rename to Desktop App/render/ceo/assets/refresh-data.webp diff --git a/CEO/render/assets/user_1144760.png b/Desktop App/render/ceo/assets/user_1144760.png similarity index 100% rename from CEO/render/assets/user_1144760.png rename to Desktop App/render/ceo/assets/user_1144760.png diff --git a/CEO/render/css/announcement.css b/Desktop App/render/ceo/css/announcement.css similarity index 100% rename from CEO/render/css/announcement.css rename to Desktop App/render/ceo/css/announcement.css diff --git a/CEO/render/css/loading.css b/Desktop App/render/ceo/css/loading.css similarity index 100% rename from CEO/render/css/loading.css rename to Desktop App/render/ceo/css/loading.css diff --git a/CEO/render/css/login.css b/Desktop App/render/ceo/css/login.css similarity index 100% rename from CEO/render/css/login.css rename to Desktop App/render/ceo/css/login.css diff --git a/CEO/render/css/main_menu.css b/Desktop App/render/ceo/css/main_menu.css similarity index 100% rename from CEO/render/css/main_menu.css rename to Desktop App/render/ceo/css/main_menu.css diff --git a/CEO/render/css/normalizer.css b/Desktop App/render/ceo/css/normalizer.css similarity index 100% rename from CEO/render/css/normalizer.css rename to Desktop App/render/ceo/css/normalizer.css diff --git a/CEO/render/css/overview_departments.css b/Desktop App/render/ceo/css/overview_departments.css similarity index 100% rename from CEO/render/css/overview_departments.css rename to Desktop App/render/ceo/css/overview_departments.css diff --git a/CEO/render/css/overview_users.css b/Desktop App/render/ceo/css/overview_users.css similarity index 100% rename from CEO/render/css/overview_users.css rename to Desktop App/render/ceo/css/overview_users.css diff --git a/CEO/render/css/profile.css b/Desktop App/render/ceo/css/profile.css similarity index 100% rename from CEO/render/css/profile.css rename to Desktop App/render/ceo/css/profile.css diff --git a/CEO/render/css/reset_password.css b/Desktop App/render/ceo/css/reset_password.css similarity index 100% rename from CEO/render/css/reset_password.css rename to Desktop App/render/ceo/css/reset_password.css diff --git a/CEO/render/css/share_file.css b/Desktop App/render/ceo/css/share_file.css similarity index 100% rename from CEO/render/css/share_file.css rename to Desktop App/render/ceo/css/share_file.css diff --git a/CEO/render/css/transition.css b/Desktop App/render/ceo/css/transition.css similarity index 100% rename from CEO/render/css/transition.css rename to Desktop App/render/ceo/css/transition.css diff --git a/CEO/render/html/announcement.html b/Desktop App/render/ceo/html/announcement.html similarity index 100% rename from CEO/render/html/announcement.html rename to Desktop App/render/ceo/html/announcement.html diff --git a/CEO/render/html/backup_retrieve.html b/Desktop App/render/ceo/html/backup_retrieve.html similarity index 100% rename from CEO/render/html/backup_retrieve.html rename to Desktop App/render/ceo/html/backup_retrieve.html diff --git a/CEO/render/html/login.html b/Desktop App/render/ceo/html/login.html similarity index 100% rename from CEO/render/html/login.html rename to Desktop App/render/ceo/html/login.html diff --git a/CEO/render/html/main_menu.html b/Desktop App/render/ceo/html/main_menu.html similarity index 100% rename from CEO/render/html/main_menu.html rename to Desktop App/render/ceo/html/main_menu.html diff --git a/CEO/render/html/overview_departments.html b/Desktop App/render/ceo/html/overview_departments.html similarity index 100% rename from CEO/render/html/overview_departments.html rename to Desktop App/render/ceo/html/overview_departments.html diff --git a/CEO/render/html/overview_users.html b/Desktop App/render/ceo/html/overview_users.html similarity index 100% rename from CEO/render/html/overview_users.html rename to Desktop App/render/ceo/html/overview_users.html diff --git a/CEO/render/html/profile.html b/Desktop App/render/ceo/html/profile.html similarity index 100% rename from CEO/render/html/profile.html rename to Desktop App/render/ceo/html/profile.html diff --git a/CEO/render/html/reset_database.html b/Desktop App/render/ceo/html/reset_database.html similarity index 100% rename from CEO/render/html/reset_database.html rename to Desktop App/render/ceo/html/reset_database.html diff --git a/CEO/render/html/reset_password.html b/Desktop App/render/ceo/html/reset_password.html similarity index 100% rename from CEO/render/html/reset_password.html rename to Desktop App/render/ceo/html/reset_password.html diff --git a/CEO/render/html/send_announcement.html b/Desktop App/render/ceo/html/send_announcement.html similarity index 100% rename from CEO/render/html/send_announcement.html rename to Desktop App/render/ceo/html/send_announcement.html diff --git a/CEO/render/html/share_file.html b/Desktop App/render/ceo/html/share_file.html similarity index 100% rename from CEO/render/html/share_file.html rename to Desktop App/render/ceo/html/share_file.html diff --git a/CEO/render/html/uc_not_found.html b/Desktop App/render/ceo/html/uc_not_found.html similarity index 100% rename from CEO/render/html/uc_not_found.html rename to Desktop App/render/ceo/html/uc_not_found.html diff --git a/CEO/render/html/welcome.html b/Desktop App/render/ceo/html/welcome.html similarity index 100% rename from CEO/render/html/welcome.html rename to Desktop App/render/ceo/html/welcome.html diff --git a/CEO/render/js/announcement.js b/Desktop App/render/ceo/js/announcement.js similarity index 81% rename from CEO/render/js/announcement.js rename to Desktop App/render/ceo/js/announcement.js index b24ec85..1f4777a 100644 --- a/CEO/render/js/announcement.js +++ b/Desktop App/render/ceo/js/announcement.js @@ -11,12 +11,12 @@ document.addEventListener('DOMContentLoaded', function () { const message = announcementTextarea.value.trim(); if (message === '') { - await window.electronAPI.showAlert('Please enter a message before sending.'); + await window.uiAPI.showAlert('Please enter a message before sending.'); return; } // Send the announcement message via the electronAPI - window.electronAPI.startAnnouncementWorker(message); + window.workersAPI.startAnnouncementWorker(message); fadeOut('send_announcement'); }); }); diff --git a/User/render/js/helpers.js b/Desktop App/render/ceo/js/helpers.js similarity index 100% rename from User/render/js/helpers.js rename to Desktop App/render/ceo/js/helpers.js diff --git a/CEO/render/js/login.js b/Desktop App/render/ceo/js/login.js similarity index 53% rename from CEO/render/js/login.js rename to Desktop App/render/ceo/js/login.js index 5d56b1b..ada7504 100644 --- a/CEO/render/js/login.js +++ b/Desktop App/render/ceo/js/login.js @@ -8,9 +8,9 @@ document.addEventListener('DOMContentLoaded', async function () { const resetPasswordButton = document.getElementById('resetPassword'); // Retrieve the operation codes via IPC - const operationCodes = await window.electronAPI.getOperationsCodes(); + const operationCodes = await window.networkAPI.getOperationsCodes(); if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); + await window.uiAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); return; } @@ -21,7 +21,7 @@ document.addEventListener('DOMContentLoaded', async function () { resetPasswordButton.addEventListener('click', function (e) { e.preventDefault(); - window.electronAPI.changeContent('reset_password'); + window.uiAPI.changeContent('reset_password'); }); // Submit button logic (handle login) @@ -36,50 +36,52 @@ document.addEventListener('DOMContentLoaded', async function () { const password = formData.get('password'); // Open a TCP socket to the stored IP - if (!await window.electronAPI.openUcSocket()) { - await window.electronAPI.showAlert('Internal error of the application. Unable to open socket.'); + if (!await window.networkAPI.openUcSocket()) { + await window.uiAPI.showAlert('Internal error of the application. Unable to open socket.'); return; } // Attempt login if (!await attemptLogin(email, password)) { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); return; } // Fetch and store user info if (!await fetchAndStoreUserInfo(email)) { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); return; } // Fetch user info from local storage - const userInfo = await window.electronAPI.readUserConfig('user_info'); + const userInfo = await window.databaseAPI.getUserInfo('user_info'); if (!userInfo) { - await window.electronAPI.closeUcSocket(); - await window.electronAPI.showAlert('Failed to fetch user info.'); + await window.networkAPI.closeUcSocket(); + await window.uiAPI.showAlert('Failed to fetch user info.'); return; } // Fetch and store encryption key if (!await fetchAndStoreEncryptionKey(userInfo.id)) { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); return; } // Close the socket and navigate to main menu after success - await window.electronAPI.closeUcSocket(); - await window.electronAPI.changeContent('main_menu'); + await window.networkAPI.closeUcSocket(); + await window.workersAPI.startWorkers(); + await window.databaseAPI.setLoginStatus(true); + await window.uiAPI.changeContent('main_menu'); }); }); async function attemptLogin(email, password) { - const app_type = await window.electronAPI.readUserConfig('app_type'); + const app_type = await window.databaseAPI.getAppType(); const messageData = {email, password, app_type}; // Send the login message to the server - if (!await window.electronAPI.sendUcMessage(codeLogin, messageData)) { - await window.electronAPI.showAlert('Failed to send login request.'); + if (!await window.networkAPI.sendUcMessage(codeLogin, messageData)) { + await window.uiAPI.showAlert('Failed to send login request.'); return false; } @@ -87,57 +89,44 @@ async function attemptLogin(email, password) { const response = await waitForResponse(); if (!response) { - await window.electronAPI.showAlert('No response from server.'); + await window.uiAPI.showAlert('No response from server.'); return false; } if (response.operationCode !== codeOk) { - await window.electronAPI.showAlert(response.metaInfo.message); + await window.uiAPI.showAlert(response.metaInfo.message); return false; } - const user_info = await window.electronAPI.readUserConfig('user_info'); - if (!user_info || (user_info && user_info.email !== email)) { - await window.electronAPI.resetApplicationInfo(); - await window.electronAPI.resetMemory(); - await window.electronAPI.resetUserConfig(); - await window.electronAPI.writeUserConfig('app_type', app_type); - await window.electronAPI.writeUserConfig('user_info', {email, password}); - return true; - } - return true; } async function fetchAndStoreUserInfo(userEmail) { - if (!await window.electronAPI.sendUcMessage(codeFindByEmail, {email: userEmail})) { - await window.electronAPI.showAlert('Failed to send request to fetch user info.'); + if (!await window.networkAPI.sendUcMessage(codeFindByEmail, {email: userEmail})) { + await window.uiAPI.showAlert('Failed to send request to fetch user info.'); return false; } // Wait for the response using waitForResponse const response = await waitForResponse(); if (response && response.operationCode === codeOk) { - let userInfo = await window.electronAPI.readUserConfig('user_info'); - if (!userInfo) { - userInfo = {}; - } - + const userInfo = {}; userInfo.id = response.metaInfo.id; + userInfo.email = response.metaInfo.email; userInfo.departmentId = response.metaInfo.departmentId; userInfo.name = response.metaInfo.name || 'User'; - await window.electronAPI.writeUserConfig('user_info', userInfo); + await window.databaseAPI.writeUserInfo(userInfo); return true; } - await window.electronAPI.showAlert('Failed to fetch user info from server.'); + await window.uiAPI.showAlert('Failed to fetch user info from server.'); return false; } async function fetchAndStoreEncryptionKey(userId) { - if (!await window.electronAPI.sendUcMessage(codeFindKeyByUser, {userId})) { - await window.electronAPI.showAlert('Failed to send request to fetch encryption key.'); + if (!await window.networkAPI.sendUcMessage(codeFindKeyByUser, {userId})) { + await window.uiAPI.showAlert('Failed to send request to fetch encryption key.'); return false; } @@ -149,10 +138,10 @@ async function fetchAndStoreEncryptionKey(userId) { iv: response.metaInfo.key.iv, }; - await window.electronAPI.writeUserConfig('encryption_key', encryptionKey); + await window.databaseAPI.writeEncryptionKey(encryptionKey); return true; } - await window.electronAPI.showAlert('Failed to fetch encryption key from server.'); + await window.uiAPI.showAlert('Failed to fetch encryption key from server.'); return false; } diff --git a/CEO/render/js/main_menu.js b/Desktop App/render/ceo/js/main_menu.js similarity index 58% rename from CEO/render/js/main_menu.js rename to Desktop App/render/ceo/js/main_menu.js index 27ad798..5ef7a73 100644 --- a/CEO/render/js/main_menu.js +++ b/Desktop App/render/ceo/js/main_menu.js @@ -29,7 +29,7 @@ document.addEventListener('DOMContentLoaded', async function () { if (userConfirmed) { await resetDatabase(); } else { - window.electronAPI.showAlert("Database reset canceled."); + window.uiAPI.showAlert("Database reset canceled."); } }); @@ -70,48 +70,52 @@ async function initialSetup(){ } async function restoreBackup() { - const backupDirectory = await window.electronAPI.readApplicationInfo('backupDirectory'); + const backupDirectory = await window.databaseAPI.isBackupSet(); - if (backupDirectory && backupDirectory.path) { - // If backup directory is already set, display an alert - await window.electronAPI.showAlert('You have already set a backup directory. You cannot restore again.'); + if (backupDirectory) { + await window.uiAPI.showAlert('You have already set a backup directory. You cannot restore again.'); return; } // Prompt the user to choose the destination for the restored backup - const destinationPath = await window.electronAPI.selectDirectory(); + const destinationPath = await window.uiAPI.selectDirectory(); if (!destinationPath) { return; // User canceled the directory selection } // Call the IPC method to initiate the backup retrieval process - window.electronAPI.startBackupRetrieval(destinationPath); + window.workersAPI.startBackupRetrieval(destinationPath); // Switch the content to the 'backup_retrieve' page fadeOut('backup_retrieve'); } async function checkAndSetAllDirectories() { - await attachNotificationButton('backupDirectory', 'Set your backup directory!', 'backup_alert', 'alert'); - await attachNotificationButton('shareDirectory', 'Set your share directory!', 'share_alert', 'alert'); - await attachNotificationButton('departmentDirectory', 'Set your department directory!', 'department_alert', 'alert'); + const directorySchemes = await window.databaseAPI.getLocalResources(); + + backupDirId = directorySchemes.backup.id; + shareDirId = directorySchemes.shared.id; + departmentDirId = directorySchemes.department.id; + + await attachNotificationButton(backupDirId, 'Set your backup directory!', 'backup_alert', 'alert'); + await attachNotificationButton(shareDirId, 'Set your share directory!', 'share_alert', 'alert'); + await attachNotificationButton(departmentDirId, 'Set your department directory!', 'department_alert', 'alert'); } -async function checkPathExistence(pathKey) { - return await window.electronAPI.readApplicationInfo(pathKey); +async function checkPathExistence(id) { + const dirInfo = await window.databaseAPI.getDirectoryInfo(id); + return dirInfo.path !== '' } -async function setPath(pathKey) { - const path = await window.electronAPI.selectDirectory(); - if (path === undefined) return; +async function setPath(id){ + const path = await window.uiAPI.selectDirectory(); + if (path === undefined) return false; - const id = await window.electronAPI.createMemoryEntry() - console.log({id, path}) - await window.electronAPI.writeApplicationInfo(pathKey, {id, path}); + return await window.databaseAPI.writeDirectoryPath(id, path); } -async function attachNotificationButton(pathKey, buttonText, buttonId, buttonName) { - const path = await checkPathExistence(pathKey); +async function attachNotificationButton(entryId, buttonText, buttonId, buttonName) { + const path = await checkPathExistence(entryId); if (!path) { const notificationsDiv = document.getElementById('notifications'); const button = document.createElement('button'); @@ -120,8 +124,7 @@ async function attachNotificationButton(pathKey, buttonText, buttonId, buttonNam button.name = buttonName; button.textContent = buttonText; button.addEventListener('click', async function () { - await setPath(pathKey); - button.remove(); // Remove button after setting the path + if(await setPath(entryId)) button.remove(); }); notificationsDiv.appendChild(button); } @@ -131,7 +134,7 @@ async function fetchUserInfo() { const usernameField = document.getElementById('username-field'); // Read the user credentials from the userConfig - let userInfo = await window.electronAPI.readUserConfig('user_info'); + let userInfo = await window.databaseAPI.getUserInfo(); if (userInfo && userInfo.name) { usernameField.textContent = userInfo.name; return; @@ -139,7 +142,7 @@ async function fetchUserInfo() { // Update the greeting with the fetched user's name if (usernameField) { - usernameField.textContent = userInfo.name; // Update the h1 with the user's name + usernameField.textContent = userInfo.name; } else { console.error("Username field is not available in the DOM."); } @@ -147,29 +150,16 @@ async function fetchUserInfo() { async function loadReceivedFiles() { // Read the shareDirectory from applicationInfo - const shareDirectoryData = await window.electronAPI.readApplicationInfo('shareDirectory'); + const shareDirData = await window.databaseAPI.getDirectoryInfo(shareDirId); - if (!shareDirectoryData || !shareDirectoryData.id) { - console.log('No received files or directory ID found.'); - return; - } - - const directoryId = shareDirectoryData.id; - - // Fetch the directory structure (JSON objects with user names and file paths) - const directoryStructure = await window.electronAPI.readMemoryEntry(directoryId); - - if (!directoryStructure || !directoryStructure.structure) { - console.log('No received files found in the directory structure.'); - return; - } + console.log('Loading received files:', shareDirData); const notificationsDiv = document.getElementById('notifications'); const existingButtons = Array.from(notificationsDiv.children).map(button => button.getAttribute('data-filepath')); // Iterate over each user and their files in the structure - Object.keys(directoryStructure.structure).forEach(userName => { - const userFiles = directoryStructure.structure[userName]; + Object.keys(shareDirData.structure).forEach(userName => { + const userFiles = shareDirData.structure[userName]; // Iterate over each file of the user Object.keys(userFiles).forEach(fileName => { @@ -189,58 +179,16 @@ async function loadReceivedFiles() { }); } -async function removeReceivedFile(filePath) { - // Read the shareDirectory from applicationInfo - const shareDirectoryData = await window.electronAPI.readApplicationInfo('shareDirectory'); - - if (!shareDirectoryData || !shareDirectoryData.id) { - console.log('No directory ID found to update.'); - return; - } - - const directoryId = shareDirectoryData.id; - - // Fetch the directory structure - let directoryStructure = await window.electronAPI.readMemoryEntry(directoryId); - - if (directoryStructure && directoryStructure.structure) { - // Iterate over each user and their files - for (let userName in directoryStructure.structure) { - let userFiles = directoryStructure.structure[userName]; - - // Check if the file exists and remove it - if (userFiles[filePath]) { - delete userFiles[filePath]; - - // Remove the user if no more files are left - if (Object.keys(userFiles).length === 0) { - delete directoryStructure.structure[userName]; - } - - // Update the directory structure in memory - await window.electronAPI.updateMemoryEntry(directoryId, directoryStructure); - console.log(`File ${filePath} removed from memory.`); - return; - } - } - } else { - console.log('No directory structure found in memory to update.'); - } -} - async function handleFileReceivedButtonPressed(filePath, button) { console.log('Notification button clicked!'); // Open the file in the file explorer - await window.electronAPI.showFileInExplorer(filePath) + await window.uiAPI.showFileInExplorer(filePath) .then(() => console.log('File explorer opened for: ' + filePath)) .catch(error => console.error('Error opening file explorer:', error)); // Remove the button after opening the file button.remove(); - - // Remove the file from memory - await removeReceivedFile(filePath); } async function showConfirmationDialog(message) { diff --git a/CEO/render/js/overview_departments.js b/Desktop App/render/ceo/js/overview_departments.js similarity index 80% rename from CEO/render/js/overview_departments.js rename to Desktop App/render/ceo/js/overview_departments.js index 0d2ddb3..0171749 100644 --- a/CEO/render/js/overview_departments.js +++ b/Desktop App/render/ceo/js/overview_departments.js @@ -10,13 +10,13 @@ document.addEventListener('DOMContentLoaded', async () => { const closeCreateModalButton = document.getElementById('closeCreateModal'); const confirmCreateButton = document.getElementById('confirmCreateButton'); - if (!await window.electronAPI.openUcSocket()) { - await window.electronAPI.showAlert('Internal error of the application. Unable to open socket.'); + if (!await window.networkAPI.openUcSocket()) { + await window.uiAPI.showAlert('Internal error of the application. Unable to open socket.'); return; } backButton.addEventListener('click', async () => { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); fadeOut('main_menu'); }); @@ -34,7 +34,7 @@ document.addEventListener('DOMContentLoaded', async () => { confirmCreateButton.addEventListener('click', async () => { const departmentName = document.getElementById('newDepartmentName').value.trim(); if (!departmentName) { - window.electronAPI.showAlert("Please enter a department name."); + window.uiAPI.showAlert("Please enter a department name."); return; } @@ -49,9 +49,9 @@ async function fetchDepartments() { departmentsContainer.innerHTML = ''; // Clear any existing data // Retrieve the operation codes via IPC - const operationCodes = await window.electronAPI.getOperationsCodes(); + const operationCodes = await window.networkAPI.getOperationsCodes(); if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); + await window.uiAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); return; } @@ -62,8 +62,8 @@ async function fetchDepartments() { codeDeleteDepartment = operationCodes.DELETE_DEPARTMENT; // Send the login message to the server - if (!await window.electronAPI.sendUcMessage(codeGetDepartments)) { - await window.electronAPI.showAlert('Failed to send login request.'); + if (!await window.networkAPI.sendUcMessage(codeGetDepartments)) { + await window.uiAPI.showAlert('Failed to send login request.'); return false; } @@ -71,7 +71,7 @@ async function fetchDepartments() { const response = await waitForResponse(); if(!response || response.operationCode !== codeOk){ - await window.electronAPI.showAlert('Could not fetch departments.'); + await window.uiAPI.showAlert('Could not fetch departments.'); return false; } @@ -129,8 +129,8 @@ async function fetchDepartments() { async function createDepartment(departmentName) { - if (!await window.electronAPI.sendUcMessage(codeCreateDepartment, { departmentName: departmentName })) { - await window.electronAPI.showAlert('Failed to send login request.'); + if (!await window.networkAPI.sendUcMessage(codeCreateDepartment, { departmentName: departmentName })) { + await window.uiAPI.showAlert('Failed to send login request.'); return false; } @@ -138,7 +138,7 @@ async function createDepartment(departmentName) { const response = await waitForResponse(); if(!response || response.operationCode !== codeOk){ - await window.electronAPI.showAlert('Could not create new department.'); + await window.uiAPI.showAlert('Could not create new department.'); return false; } @@ -146,8 +146,8 @@ async function createDepartment(departmentName) { } async function modifyDepartment(departmentId, newDepartmentName) { - if (!await window.electronAPI.sendUcMessage(codeModifyDepartment, { departmentId: departmentId, newDepartmentName: newDepartmentName })) { - await window.electronAPI.showAlert('Failed to send modify request.'); + if (!await window.networkAPI.sendUcMessage(codeModifyDepartment, { departmentId: departmentId, newDepartmentName: newDepartmentName })) { + await window.uiAPI.showAlert('Failed to send modify request.'); return false; } @@ -155,7 +155,7 @@ async function modifyDepartment(departmentId, newDepartmentName) { const response = await waitForResponse(); if(!response || response.operationCode !== codeOk){ - await window.electronAPI.showAlert('Could not modify department.'); + await window.uiAPI.showAlert('Could not modify department.'); console.log(response.metaInfo.message); return false; } @@ -167,15 +167,15 @@ async function deleteDepartment(departmentId) { const confirmDelete = confirm("Are you sure you want to delete this department?"); if (!confirmDelete) return; - if (!await window.electronAPI.sendUcMessage(codeDeleteDepartment, { departmentId: departmentId })) { - await window.electronAPI.showAlert('Failed to send delete request.'); + if (!await window.networkAPI.sendUcMessage(codeDeleteDepartment, { departmentId: departmentId })) { + await window.uiAPI.showAlert('Failed to send delete request.'); return false; } const response = await waitForResponse(); if(!response || response.operationCode !== codeOk){ - await window.electronAPI.showAlert('Could not delete department.'); + await window.uiAPI.showAlert('Could not delete department.'); return false; } @@ -199,7 +199,7 @@ function openModifyModal(departmentId, departmentName) { console.log(newDepartmentName, departmentId); if (!newDepartmentName || !departmentId) { - window.electronAPI.showAlert("Please enter a new department name."); + window.uiAPI.showAlert("Please enter a new department name."); return; } await modifyDepartment(departmentId, newDepartmentName); diff --git a/CEO/render/js/overview_users.js b/Desktop App/render/ceo/js/overview_users.js similarity index 89% rename from CEO/render/js/overview_users.js rename to Desktop App/render/ceo/js/overview_users.js index 23c9127..3efd9a0 100644 --- a/CEO/render/js/overview_users.js +++ b/Desktop App/render/ceo/js/overview_users.js @@ -6,15 +6,15 @@ let codeOk = ''; document.addEventListener('DOMContentLoaded', async () => { const backButton = document.getElementById('backButton'); backButton.addEventListener('click', async () => { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); fadeOut('main_menu'); }); }); async function fetchData() { - const operationCodes = await window.electronAPI.getOperationsCodes(); + const operationCodes = await window.networkAPI.getOperationsCodes(); if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); + await window.uiAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); return; } @@ -24,7 +24,7 @@ async function fetchData() { codeOk = operationCodes.OK; // Open the TCP socket right after fetching the operation codes - if (!await window.electronAPI.openUcSocket()) { + if (!await window.networkAPI.openUcSocket()) { alert('Failed to open socket. Internal error of the application.'); return; } @@ -114,7 +114,7 @@ async function fetchData() { async function fetchDepartments() { // Send the request to get departments - if (!await window.electronAPI.sendUcMessage(codeGetDepartments)) { + if (!await window.networkAPI.sendUcMessage(codeGetDepartments)) { return null; } return await waitForResponse(); @@ -122,7 +122,7 @@ async function fetchDepartments() { async function fetchUsers() { // Send the request to get users - if (!await window.electronAPI.sendUcMessage(codeGetUsers)) { + if (!await window.networkAPI.sendUcMessage(codeGetUsers)) { return null; } return await waitForResponse(); @@ -130,7 +130,7 @@ async function fetchUsers() { async function deleteUser(userId) { // Send the request to delete the user - if (!await window.electronAPI.sendUcMessage(codeDeleteUser, {id: userId})) { + if (!await window.networkAPI.sendUcMessage(codeDeleteUser, {id: userId})) { alert('Failed to send request to delete user.'); return; } @@ -145,6 +145,6 @@ async function deleteUser(userId) { } async function redirectToMainMenu() { - await window.electronAPI.closeUcSocket(); + await window.networkAPI.closeUcSocket(); fadeOut('main_menu'); } diff --git a/User/render/js/profile.js b/Desktop App/render/ceo/js/profile.js similarity index 100% rename from User/render/js/profile.js rename to Desktop App/render/ceo/js/profile.js diff --git a/Desktop App/render/ceo/js/reset_database.js b/Desktop App/render/ceo/js/reset_database.js new file mode 100644 index 0000000..9fdba1b --- /dev/null +++ b/Desktop App/render/ceo/js/reset_database.js @@ -0,0 +1,31 @@ +document.addEventListener('DOMContentLoaded', async function () { + const operationCodes = await window.networkAPI.getOperationsCodes(); + if (!operationCodes) { + await window.uiAPI.showAlert('Internal error of the application. Failed to retrieve operation codes.'); + return; + } + + const codeResetDatabase = operationCodes.RESET_DATABASE; + const codeOk = operationCodes.OK; + + // Open a TCP socket to the stored IP + if (!await window.networkAPI.openUcSocket()) { + await window.uiAPI.showAlert('Internal error of the application. Unable to open socket.'); + return; + } + + if (!await window.networkAPI.sendUcMessage(codeResetDatabase)) { + await window.uiAPI.showAlert('Failed to send login request.'); + return; + } + + const response = await waitForResponse(); + if (response && response.operationCode !== codeOk) { + await window.uiAPI.showAlert('Database reset failed.'); + return; + } + + await window.networkAPI.closeUcSocket(); + await new Promise(resolve => setTimeout(resolve, 2000)); + fadeOut('login'); +}); \ No newline at end of file diff --git a/User/render/js/reset_password.js b/Desktop App/render/ceo/js/reset_password.js similarity index 100% rename from User/render/js/reset_password.js rename to Desktop App/render/ceo/js/reset_password.js diff --git a/User/render/js/share_file.js b/Desktop App/render/ceo/js/share_file.js similarity index 100% rename from User/render/js/share_file.js rename to Desktop App/render/ceo/js/share_file.js diff --git a/User/render/assets/2581896.png b/Desktop App/render/client/assets/2581896.png similarity index 100% rename from User/render/assets/2581896.png rename to Desktop App/render/client/assets/2581896.png diff --git a/User/render/assets/cloud-computing.webp b/Desktop App/render/client/assets/cloud-computing.webp similarity index 100% rename from User/render/assets/cloud-computing.webp rename to Desktop App/render/client/assets/cloud-computing.webp diff --git a/User/render/assets/hard-disk.ico b/Desktop App/render/client/assets/hard-disk.ico similarity index 100% rename from User/render/assets/hard-disk.ico rename to Desktop App/render/client/assets/hard-disk.ico diff --git a/User/render/assets/icon.icns b/Desktop App/render/client/assets/icon.icns similarity index 100% rename from User/render/assets/icon.icns rename to Desktop App/render/client/assets/icon.icns diff --git a/User/render/assets/icon.ico b/Desktop App/render/client/assets/icon.ico similarity index 100% rename from User/render/assets/icon.ico rename to Desktop App/render/client/assets/icon.ico diff --git a/User/render/assets/icon.png b/Desktop App/render/client/assets/icon.png similarity index 100% rename from User/render/assets/icon.png rename to Desktop App/render/client/assets/icon.png diff --git a/User/render/assets/refresh-data.webp b/Desktop App/render/client/assets/refresh-data.webp similarity index 100% rename from User/render/assets/refresh-data.webp rename to Desktop App/render/client/assets/refresh-data.webp diff --git a/User/render/assets/user_1144760.png b/Desktop App/render/client/assets/user_1144760.png similarity index 100% rename from User/render/assets/user_1144760.png rename to Desktop App/render/client/assets/user_1144760.png diff --git a/User/render/css/announcement.css b/Desktop App/render/client/css/announcement.css similarity index 100% rename from User/render/css/announcement.css rename to Desktop App/render/client/css/announcement.css diff --git a/User/render/css/loading.css b/Desktop App/render/client/css/loading.css similarity index 100% rename from User/render/css/loading.css rename to Desktop App/render/client/css/loading.css diff --git a/User/render/css/login.css b/Desktop App/render/client/css/login.css similarity index 100% rename from User/render/css/login.css rename to Desktop App/render/client/css/login.css diff --git a/User/render/css/main_menu.css b/Desktop App/render/client/css/main_menu.css similarity index 100% rename from User/render/css/main_menu.css rename to Desktop App/render/client/css/main_menu.css diff --git a/User/render/css/normalizer.css b/Desktop App/render/client/css/normalizer.css similarity index 100% rename from User/render/css/normalizer.css rename to Desktop App/render/client/css/normalizer.css diff --git a/User/render/css/profile.css b/Desktop App/render/client/css/profile.css similarity index 100% rename from User/render/css/profile.css rename to Desktop App/render/client/css/profile.css diff --git a/User/render/css/reset_password.css b/Desktop App/render/client/css/reset_password.css similarity index 100% rename from User/render/css/reset_password.css rename to Desktop App/render/client/css/reset_password.css diff --git a/User/render/css/share_file.css b/Desktop App/render/client/css/share_file.css similarity index 100% rename from User/render/css/share_file.css rename to Desktop App/render/client/css/share_file.css diff --git a/User/render/css/sign_up.css b/Desktop App/render/client/css/sign_up.css similarity index 100% rename from User/render/css/sign_up.css rename to Desktop App/render/client/css/sign_up.css diff --git a/User/render/css/transition.css b/Desktop App/render/client/css/transition.css similarity index 100% rename from User/render/css/transition.css rename to Desktop App/render/client/css/transition.css diff --git a/User/render/html/announcement.html b/Desktop App/render/client/html/announcement.html similarity index 100% rename from User/render/html/announcement.html rename to Desktop App/render/client/html/announcement.html diff --git a/User/render/html/backup_retrieve.html b/Desktop App/render/client/html/backup_retrieve.html similarity index 100% rename from User/render/html/backup_retrieve.html rename to Desktop App/render/client/html/backup_retrieve.html diff --git a/User/render/html/login.html b/Desktop App/render/client/html/login.html similarity index 100% rename from User/render/html/login.html rename to Desktop App/render/client/html/login.html diff --git a/User/render/html/main_menu.html b/Desktop App/render/client/html/main_menu.html similarity index 100% rename from User/render/html/main_menu.html rename to Desktop App/render/client/html/main_menu.html diff --git a/User/render/html/profile.html b/Desktop App/render/client/html/profile.html similarity index 100% rename from User/render/html/profile.html rename to Desktop App/render/client/html/profile.html diff --git a/User/render/html/reset_database.html b/Desktop App/render/client/html/reset_database.html similarity index 100% rename from User/render/html/reset_database.html rename to Desktop App/render/client/html/reset_database.html diff --git a/User/render/html/reset_password.html b/Desktop App/render/client/html/reset_password.html similarity index 100% rename from User/render/html/reset_password.html rename to Desktop App/render/client/html/reset_password.html diff --git a/User/render/html/share_file.html b/Desktop App/render/client/html/share_file.html similarity index 100% rename from User/render/html/share_file.html rename to Desktop App/render/client/html/share_file.html diff --git a/User/render/html/sign_up.html b/Desktop App/render/client/html/sign_up.html similarity index 100% rename from User/render/html/sign_up.html rename to Desktop App/render/client/html/sign_up.html diff --git a/User/render/html/uc_not_found.html b/Desktop App/render/client/html/uc_not_found.html similarity index 100% rename from User/render/html/uc_not_found.html rename to Desktop App/render/client/html/uc_not_found.html diff --git a/User/render/html/welcome.html b/Desktop App/render/client/html/welcome.html similarity index 100% rename from User/render/html/welcome.html rename to Desktop App/render/client/html/welcome.html diff --git a/User/render/js/announcement.js b/Desktop App/render/client/js/announcement.js similarity index 100% rename from User/render/js/announcement.js rename to Desktop App/render/client/js/announcement.js diff --git a/CEO/render/js/helpers.js b/Desktop App/render/client/js/helpers.js similarity index 84% rename from CEO/render/js/helpers.js rename to Desktop App/render/client/js/helpers.js index b770ad0..bc69ed1 100644 --- a/CEO/render/js/helpers.js +++ b/Desktop App/render/client/js/helpers.js @@ -13,7 +13,7 @@ function fadeOut(destination) { container.addEventListener('animationend', async () => { try { - await window.electronAPI.changeContent(destination); + await window.uiAPI.changeContent(destination); console.log('Navigated to', destination); } catch (error) { console.error('Error navigating:', error); @@ -24,9 +24,9 @@ function fadeOut(destination) { async function waitForResponse() { return new Promise((resolve) => { const idResponseCheck = setInterval(async () => { - if (await window.electronAPI.hasResponseArrived()) { + if (await window.networkAPI.hasResponseArrived()) { clearInterval(idResponseCheck); - resolve(await window.electronAPI.getLastUcResult()); // Resolve the response or null if not available + resolve(await window.networkAPI.getLastUcResult()); // Resolve the response or null if not available } }, 100); // Check every 100 milliseconds if the response has arrived }); diff --git a/User/render/js/login.js b/Desktop App/render/client/js/login.js similarity index 99% rename from User/render/js/login.js rename to Desktop App/render/client/js/login.js index 811bc59..ff1d649 100644 --- a/User/render/js/login.js +++ b/Desktop App/render/client/js/login.js @@ -77,7 +77,7 @@ document.addEventListener('DOMContentLoaded', async function () { // Close the socket and navigate to main menu after success await window.networkAPI.closeUcSocket(); - await window.uiAPI.startWorkers(); + await window.workersAPI.startWorkers(); await window.databaseAPI.setLoginStatus(true); await window.uiAPI.changeContent('main_menu'); }); diff --git a/User/render/js/main_menu.js b/Desktop App/render/client/js/main_menu.js similarity index 99% rename from User/render/js/main_menu.js rename to Desktop App/render/client/js/main_menu.js index c60e607..61efd3a 100644 --- a/User/render/js/main_menu.js +++ b/Desktop App/render/client/js/main_menu.js @@ -65,7 +65,7 @@ async function restoreBackup() { } // Call the IPC method to initiate the backup retrieval process - window.uiAPI.startBackupRetrieval(destinationPath); + window.workersAPI.startBackupRetrieval(destinationPath); // Switch the content to the 'backup_retrieve' page fadeOut('backup_retrieve'); diff --git a/CEO/render/js/profile.js b/Desktop App/render/client/js/profile.js similarity index 66% rename from CEO/render/js/profile.js rename to Desktop App/render/client/js/profile.js index 44f715e..2c6de5b 100644 --- a/CEO/render/js/profile.js +++ b/Desktop App/render/client/js/profile.js @@ -1,22 +1,27 @@ +let id = ''; +let departmentId = ''; + document.addEventListener('DOMContentLoaded', async function () { - const {email, password, name} = await window.electronAPI.readUserConfig('user_info'); + const {id: userId, name, email, departmentId: userDepartmentId} = await window.databaseAPI.getUserInfo(); const emailInput = document.querySelector('input[name="email"]'); const usernameInput = document.querySelector('input[name="username"]'); const passwordInput = document.querySelector('input[name="password"]'); // Pre-fill form fields with existing data - emailInput.value = email; + id = userId + departmentId = userDepartmentId; usernameInput.value = name; - passwordInput.value = password; + emailInput.value = email; + passwordInput.value = ''; const backButton = document.getElementById('back'); const submitButton = document.getElementById('submit'); // Get operation codes from the backend - const operationCodes = await window.electronAPI.getOperationsCodes(); + const operationCodes = await window.networkAPI.getOperationsCodes(); if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application.'); + await window.uiAPI.showAlert('Internal error of the application.'); return; } @@ -39,8 +44,7 @@ document.addEventListener('DOMContentLoaded', async function () { const name = usernameInput.value; const password = passwordInput.value; - const { id, departmentId } = await window.electronAPI.readUserConfig('user_info'); // Fetch login data - const app_type = await window.electronAPI.readUserConfig('app_type'); // Fetch app type + const app_type = await window.databaseAPI.getAppType(); // Prepare the data to be sent via the UC socket const messageData = { @@ -49,18 +53,18 @@ document.addEventListener('DOMContentLoaded', async function () { email: email, password: password, departmentId: departmentId, - app_type: app_type // Include app_type in the payload + app_type: app_type }; // Open UC socket - if (!await window.electronAPI.openUcSocket()) { - await window.electronAPI.showAlert('Failed to open socket. Internal error of the application.'); + if (!await window.networkAPI.openUcSocket()) { + await window.uiAPI.showAlert('Failed to open socket. Internal error of the application.'); return; } // Send the message to the server using the UC socket - if (!await window.electronAPI.sendUcMessage(codeModifyUser, messageData)) { - await window.electronAPI.showAlert('Failed to send message.'); + if (!await window.networkAPI.sendUcMessage(codeModifyUser, messageData)) { + await window.uiAPI.showAlert('Failed to send message.'); return; } @@ -70,8 +74,7 @@ document.addEventListener('DOMContentLoaded', async function () { console.log('User update successful.'); // Save updated user info to the userConfig - await window.electronAPI.writeUserConfig('user_credentials', { email: email, password: password }); - await window.electronAPI.writeUserConfig('user_info', {id: id, departmentId: departmentId, name: name}); + await window.databaseAPI.writeUserInfo({ id: id, email: email, name: name, departmentId: departmentId }); // Navigate back to the main menu fadeOut('main_menu'); diff --git a/User/render/js/reset_database.js b/Desktop App/render/client/js/reset_database.js similarity index 84% rename from User/render/js/reset_database.js rename to Desktop App/render/client/js/reset_database.js index 30fda71..c4a0204 100644 --- a/User/render/js/reset_database.js +++ b/Desktop App/render/client/js/reset_database.js @@ -1,6 +1,6 @@ document.addEventListener('DOMContentLoaded', async function () { await new Promise(resolve => setTimeout(resolve, 7000)); await window.databaseAPI.resetInternalDatabase(); - await window.uiAPI.stopWorkers(); + await window.workersAPI.stopWorkers(); await window.uiAPI.changeContent('welcome'); }); \ No newline at end of file diff --git a/CEO/render/js/reset_password.js b/Desktop App/render/client/js/reset_password.js similarity index 61% rename from CEO/render/js/reset_password.js rename to Desktop App/render/client/js/reset_password.js index 667ae4c..80a02ac 100644 --- a/CEO/render/js/reset_password.js +++ b/Desktop App/render/client/js/reset_password.js @@ -6,9 +6,9 @@ document.addEventListener('DOMContentLoaded', async function () { const resetPasswordButton = document.getElementById('resetPassword'); // Retrieve the operation codes via IPC - const operationCodes = await window.electronAPI.getOperationsCodes(); + const operationCodes = await window.networkAPI.getOperationsCodes(); if (!operationCodes) { - await window.electronAPI.showAlert('Internal error of the application.'); + await window.uiAPI.showAlert('Internal error of the application.'); return; } @@ -18,14 +18,14 @@ document.addEventListener('DOMContentLoaded', async function () { // Back to login backToLoginButton.addEventListener('click', function (e) { e.preventDefault(); - window.electronAPI.changeContent('login'); + window.uiAPI.changeContent('login'); }); // Reset password logic resetPasswordButton.addEventListener('click', async function (e) { e.preventDefault(); - if (!await window.electronAPI.openUcSocket()) { - await window.electronAPI.showAlert('Internal error of the application.'); + if (!await window.networkAPI.openUcSocket()) { + await window.uiAPI.showAlert('Internal error of the application.'); return; } @@ -36,7 +36,7 @@ document.addEventListener('DOMContentLoaded', async function () { // Ensure the email and new password are provided if (!email || !newPassword) { - await window.electronAPI.showAlert('Please provide both email and new password.'); + await window.uiAPI.showAlert('Please provide both email and new password.'); return; } @@ -44,23 +44,23 @@ document.addEventListener('DOMContentLoaded', async function () { return; } - await window.electronAPI.closeUcSocket(); - await window.electronAPI.showAlert('Password reset successfully.'); - window.electronAPI.changeContent('login'); + await window.networkAPI.closeUcSocket(); + await window.uiAPI.showAlert('Password reset successfully.'); + await window.uiAPI.changeContent('login'); }); }); async function attemptResetPassword(email, newPassword) { - const app_type = await window.electronAPI.readUserConfig('app_type'); + const app_type = await window.databaseAPI.getAppType(); const messageData = { email, newPassword, app_type }; - if (!await window.electronAPI.sendUcMessage(codeResetPassword, messageData)) return false; + if (!await window.networkAPI.sendUcMessage(codeResetPassword, messageData)) return false; const response = await waitForResponse(); if (response && response.operationCode === codeOk) { return true; } else { - await window.electronAPI.showAlert(response?.metaInfo?.message || 'Error resetting password.'); + await window.uiAPI.showAlert(response?.metaInfo?.message || 'Error resetting password.'); return false; } } diff --git a/CEO/render/js/share_file.js b/Desktop App/render/client/js/share_file.js similarity index 79% rename from CEO/render/js/share_file.js rename to Desktop App/render/client/js/share_file.js index 5b5eb45..df0a687 100644 --- a/CEO/render/js/share_file.js +++ b/Desktop App/render/client/js/share_file.js @@ -9,7 +9,7 @@ document.addEventListener('DOMContentLoaded', async function () { selectFileButton.addEventListener('click', async function (event) { event.preventDefault(); try { - pathToFile = await window.electronAPI.selectFile(); + pathToFile = await window.uiAPI.selectFile(); updateFileName(); } catch (error) { console.error('Error opening file dialog:', error); @@ -20,11 +20,11 @@ document.addEventListener('DOMContentLoaded', async function () { // Check if a file was chosen if (!pathToFile.trim()) { - await window.electronAPI.showAlert('File not chosen!'); + await window.uiAPI.showAlert('File not chosen!'); return; } - const user_info = await window.electronAPI.readUserConfig('user_info'); + const user_info = await window.databaseAPI.getUserInfo(); if (!user_info) { return; } @@ -36,7 +36,7 @@ document.addEventListener('DOMContentLoaded', async function () { .map(checkbox => checkbox.value); // Get IP of the selected users if (!selectedUserIps.length) { - await window.electronAPI.showAlert('No user selected!'); + await window.uiAPI.showAlert('No user selected!'); return; } @@ -48,8 +48,8 @@ document.addEventListener('DOMContentLoaded', async function () { path: pathToFile, // File path userName: user_info.name // Sender's username from userConfig }; - await window.electronAPI.addTaskToSendFileQueue(task); - await window.electronAPI.showAlert('File sent to the queue.'); + await window.databaseAPI.addTaskToSendFileQueue(task); + await window.uiAPI.showAlert('File sent to the queue.'); console.log(`Task added to send file to IP ${selectedUserIp}`); } catch (error) { console.error(`Error processing IP ${selectedUserIp}:`, error); @@ -85,18 +85,13 @@ async function fetchUsersAndCreateCheckboxes() { .map(checkbox => checkbox.value) ); - const usersInfoId = await window.electronAPI.readApplicationInfo('active_users_info'); - if (!usersInfoId) { - await window.electronAPI.showAlert('Internal error.'); - return; - } - - const usersInfo = await window.electronAPI.readMemoryEntry(usersInfoId); - if (!usersInfo || usersInfo.length === 0) { - await window.electronAPI.showAlert('No active users found.'); + const usersInfo = await window.databaseAPI.getActiveUsers(); + const filteredUsers = usersInfo.filter(user => user.id !== ''); + if (!filteredUsers.length === 0) { + await window.uiAPI.showAlert('No active users found.'); clearInterval(fetchUsersInterval); fetchUsersInterval = null; - await window.electronAPI.changeContent('main_menu'); + await window.uiAPI.changeContent('main_menu'); return; } @@ -115,7 +110,7 @@ async function fetchUsersAndCreateCheckboxes() { } const label = document.createElement('label'); - label.innerHTML = `${user.user_info.name}`; // Display user's name + label.innerHTML = `${user.name}`; label.insertBefore(checkbox, label.firstChild); usersDiv.appendChild(label); diff --git a/User/render/js/sign_up.js b/Desktop App/render/client/js/sign_up.js similarity index 100% rename from User/render/js/sign_up.js rename to Desktop App/render/client/js/sign_up.js diff --git a/User/src/database/database.ts b/Desktop App/src/database/database.ts similarity index 95% rename from User/src/database/database.ts rename to Desktop App/src/database/database.ts index 9a08106..16906b0 100644 --- a/User/src/database/database.ts +++ b/Desktop App/src/database/database.ts @@ -3,10 +3,15 @@ import { promises as fs } from 'fs' import { v4 as uuidv4 } from 'uuid' import { DatabaseScheme } from './schemes/database_scheme' import { FileItemTask } from './schemes/local_resources_scheme' +import dotenv from 'dotenv' +import path from 'path' + +dotenv.config({ path: path.join(__dirname, '..', '..', '..', '.env') }) +const IS_CLIENT = process.env.IS_CLIENT === 'true' const defaultData: DatabaseScheme = { app_config: { - app_type: 'client', + app_type: IS_CLIENT ? 'client' : 'ceo', user_info: { id: '', email: '', diff --git a/User/src/database/schemes/app_config_scheme.ts b/Desktop App/src/database/schemes/app_config_scheme.ts similarity index 100% rename from User/src/database/schemes/app_config_scheme.ts rename to Desktop App/src/database/schemes/app_config_scheme.ts diff --git a/User/src/database/schemes/database_scheme.ts b/Desktop App/src/database/schemes/database_scheme.ts similarity index 100% rename from User/src/database/schemes/database_scheme.ts rename to Desktop App/src/database/schemes/database_scheme.ts diff --git a/User/src/database/schemes/local_resources_scheme.ts b/Desktop App/src/database/schemes/local_resources_scheme.ts similarity index 100% rename from User/src/database/schemes/local_resources_scheme.ts rename to Desktop App/src/database/schemes/local_resources_scheme.ts diff --git a/User/src/database/schemes/network_scheme.ts b/Desktop App/src/database/schemes/network_scheme.ts similarity index 100% rename from User/src/database/schemes/network_scheme.ts rename to Desktop App/src/database/schemes/network_scheme.ts diff --git a/Desktop App/src/helpers/announcement_sender.ts b/Desktop App/src/helpers/announcement_sender.ts new file mode 100644 index 0000000..3ff0404 --- /dev/null +++ b/Desktop App/src/helpers/announcement_sender.ts @@ -0,0 +1,113 @@ +import { TcpCommunicator } from './tcp_communicator' +import { operationCodes } from '../network/operation_codes' +import { ParsedMessage } from '../network/message_handler' +import { Database } from '../database/database' + +export class AnnouncementSender { + private readonly db: Database + private readonly port: number + private message: string = '' + private tcpCommunicator: TcpCommunicator | null = null + private stopRequested: boolean = false + + constructor(pathToDatabaseFile: string, port: number) { + this.db = new Database(pathToDatabaseFile) + this.port = port + } + + async start(message: string): Promise { + console.log('AnnouncementWorker started.') + this.message = message + this.stopRequested = false + + try { + const data = await this.db.read() + + const activeUsersIp = data.network.usersInLan.map((user) => user.ip) + if (!activeUsersIp || !activeUsersIp.length) { + throw new Error('No active users found.') + } + + for (const ip of activeUsersIp) { + if (this.stopRequested) { + console.log('AnnouncementWorker stopped.') + break + } + + const success = await this.sendAnnouncementToIp(ip) + if (!success) { + throw new Error(`Failed to send announcement to all users.`) + } + console.log(`Announcement sent and confirmed successfully from ${ip}`) + } + + process.send?.({ + type: 'showAlert', + message: 'Announcement sent to all active users successfully.', + }) + } catch (error: any) { + console.error('Error in AnnouncementWorker:', error) + process.send?.({ type: 'shotAlert', message: `A problem occurred: ${error.message}` }) + } + + console.log('AnnouncementWorker finished.') + } + + async stop(): Promise { + console.log('Stopping AnnouncementWorker...') + this.stopRequested = true + if (this.tcpCommunicator) { + await this.tcpCommunicator.disconnect() + } + console.log('AnnouncementWorker stopped.') + } + + private async sendAnnouncementToIp(ip: string): Promise { + this.tcpCommunicator = new TcpCommunicator(ip, this.port) + if (!(await this.tcpCommunicator.connect())) { + console.log(`Skipping user at IP ${ip} - unable to connect.`) + return true + } + + // Prepare the message metadata + const metaInfo = { message: this.message } + + // Send the announcement message + const messageSent = await this.tcpCommunicator.sendMessage( + operationCodes.SEND_ANNOUNCEMENT, + metaInfo, + ) + if (!messageSent) { + await this.tcpCommunicator.disconnect() + return false + } + + // Await confirmation from the user + const response = await this.waitForResponse() + if (response?.operationCode === operationCodes.OK) { + await this.tcpCommunicator.disconnect() + return true + } + + // If confirmation is not OK, disconnect and halt + await this.tcpCommunicator.disconnect() + return false + } + + private async waitForResponse(): Promise { + return new Promise((resolve) => { + const idResponseCheck = setInterval(async () => { + if (this.stopRequested || !this.tcpCommunicator) { + clearInterval(idResponseCheck) + resolve(null) + return + } + + if (this.tcpCommunicator.hasResponseArrived()) { + clearInterval(idResponseCheck) + resolve(this.tcpCommunicator.getLastResult()) + } + }, 100) + }) + } +} diff --git a/User/src/helpers/backup_manager.ts b/Desktop App/src/helpers/backup_manager.ts similarity index 100% rename from User/src/helpers/backup_manager.ts rename to Desktop App/src/helpers/backup_manager.ts diff --git a/User/src/helpers/backup_retrieval.ts b/Desktop App/src/helpers/backup_retrieval.ts similarity index 100% rename from User/src/helpers/backup_retrieval.ts rename to Desktop App/src/helpers/backup_retrieval.ts diff --git a/User/src/helpers/department_sharer.ts b/Desktop App/src/helpers/department_sharer.ts similarity index 100% rename from User/src/helpers/department_sharer.ts rename to Desktop App/src/helpers/department_sharer.ts diff --git a/User/src/helpers/directory_watcher.ts b/Desktop App/src/helpers/directory_watcher.ts similarity index 100% rename from User/src/helpers/directory_watcher.ts rename to Desktop App/src/helpers/directory_watcher.ts diff --git a/User/src/helpers/file_encryptor.ts b/Desktop App/src/helpers/file_encryptor.ts similarity index 100% rename from User/src/helpers/file_encryptor.ts rename to Desktop App/src/helpers/file_encryptor.ts diff --git a/User/src/helpers/file_sharer.ts b/Desktop App/src/helpers/file_sharer.ts similarity index 100% rename from User/src/helpers/file_sharer.ts rename to Desktop App/src/helpers/file_sharer.ts diff --git a/User/src/helpers/network_scanner.ts b/Desktop App/src/helpers/network_scanner.ts similarity index 100% rename from User/src/helpers/network_scanner.ts rename to Desktop App/src/helpers/network_scanner.ts diff --git a/User/src/helpers/tcp_communicator.ts b/Desktop App/src/helpers/tcp_communicator.ts similarity index 100% rename from User/src/helpers/tcp_communicator.ts rename to Desktop App/src/helpers/tcp_communicator.ts diff --git a/User/src/helpers/window_manager.ts b/Desktop App/src/helpers/window_manager.ts similarity index 96% rename from User/src/helpers/window_manager.ts rename to Desktop App/src/helpers/window_manager.ts index 9e674ee..416548b 100644 --- a/User/src/helpers/window_manager.ts +++ b/Desktop App/src/helpers/window_manager.ts @@ -1,4 +1,4 @@ -import {app, BrowserWindow, dialog, shell} from 'electron' +import { app, BrowserWindow, dialog, shell } from 'electron' import fs from 'fs' import path from 'path' @@ -61,7 +61,7 @@ export class WindowManager { async selectDirectory(): Promise { const result = await dialog.showOpenDialog(this.mainWindow, { properties: ['openDirectory'], // Only allow selecting directories - defaultPath: app.getPath('home') + defaultPath: app.getPath('home'), }) if (result.filePaths && result.filePaths.length > 0) { @@ -92,9 +92,7 @@ export class WindowManager { const result = await dialog.showOpenDialog(this.mainWindow, { properties: ['openFile'], // Allow selecting a file defaultPath: app.getPath('desktop'), - filters: [ - { name: 'All Files', extensions: ['*'] }, - ], + filters: [{ name: 'All Files', extensions: ['*'] }], }) if (result.filePaths && result.filePaths.length > 0) { diff --git a/User/src/helpers/worker_manager.ts b/Desktop App/src/helpers/worker_manager.ts similarity index 92% rename from User/src/helpers/worker_manager.ts rename to Desktop App/src/helpers/worker_manager.ts index 12977f5..0323431 100644 --- a/User/src/helpers/worker_manager.ts +++ b/Desktop App/src/helpers/worker_manager.ts @@ -68,6 +68,18 @@ export class WorkerManager { }) } + async startAnnouncementWorker( + pathToDatabaseFile: string, + clientPort: number, + message: string, + ): Promise { + return this.startForkedWorker('send_announcement_worker.js', { + DATABASE_FILE_PATH: pathToDatabaseFile, + CLIENT_PORT: clientPort.toString(), + MESSAGE: message, + }) + } + private async startForkedWorker( scriptName: string, envData: { [key: string]: string }, diff --git a/User/src/ipc-handlers/database_handler.ts b/Desktop App/src/ipc-handlers/database_handler.ts similarity index 100% rename from User/src/ipc-handlers/database_handler.ts rename to Desktop App/src/ipc-handlers/database_handler.ts diff --git a/User/src/ipc-handlers/uc_handler.ts b/Desktop App/src/ipc-handlers/uc_handler.ts similarity index 100% rename from User/src/ipc-handlers/uc_handler.ts rename to Desktop App/src/ipc-handlers/uc_handler.ts diff --git a/User/src/ipc-handlers/ui_handler.ts b/Desktop App/src/ipc-handlers/ui_handler.ts similarity index 100% rename from User/src/ipc-handlers/ui_handler.ts rename to Desktop App/src/ipc-handlers/ui_handler.ts diff --git a/User/src/main/main.ts b/Desktop App/src/main/main.ts similarity index 87% rename from User/src/main/main.ts rename to Desktop App/src/main/main.ts index f3c9b29..fa7d08a 100644 --- a/User/src/main/main.ts +++ b/Desktop App/src/main/main.ts @@ -11,9 +11,11 @@ import { Database } from '../database/database' // Load environment variables dotenv.config({ path: path.join(__dirname, '..', '..', '.env') }) +console.log(path.join(__dirname, '..', '..', '.env')) const UDP_PORT = process.env.UDP_PORT ? parseInt(process.env.UDP_PORT) : 41233 const TCP_PORT = process.env.TCP_PORT ? parseInt(process.env.TCP_PORT) : 41234 +const IS_CLIENT = process.env.IS_CLIENT === 'true' const HOST = getLocalIp() let mainWindow: BrowserWindow | null = null @@ -21,27 +23,29 @@ let windowManager: WindowManager | null = null let db: Database | null = null let workerManager: WorkerManager | null = null let announcementWatcher: NodeJS.Timeout | null = null -let resetApplicationWatcher: NodeJS.Timeout | null = null -const pathToPagesDir = path.join(__dirname, '..', '..', 'render', 'html') +const pathToPagesDir = path.join( + __dirname, + '..', + '..', + 'render', + IS_CLIENT ? 'client' : 'ceo', + 'html', +) const pathToWorkerDir = path.join(__dirname, '..', 'workers') const pathToDatabaseFile = path.join(__dirname, '..', 'database.json') const pathToClientsBackups = path.join(__dirname, '..', 'backups') async function cleanupAndExit() { - // Stop all workers if (workerManager) { console.log('Terminating all workers...') workerManager.closeAllWorkers() } - if (workerManager) { - console.log('Terminating all workers...') - workerManager.closeAllWorkers() - } + if (announcementWatcher) clearInterval(announcementWatcher) console.log('Cleanup complete, exiting application.') - app.quit() // This will properly close the application + app.quit() } async function ensureDirectoryExists(dirPath: string): Promise { @@ -80,23 +84,8 @@ function startAnnouncementWatcher() { }, checkInterval) } -function startResetApplicationWatcher() { - const checkInterval = 5000 // Check every 5 seconds - - resetApplicationWatcher = setInterval(async () => { - /* - if (!applicationInfo || !windowManager) return - const resetApplicationPreferences = await applicationInfo.readValue( - 'reset_application_preferences', - ) - - if (resetApplicationPreferences) await windowManager.changeContent('reset-database') - */ - }, checkInterval) -} - app.whenReady().then(async () => { - const title = 'Application' + const title = 'TeamVault' const mainScreen = require('electron').screen.getPrimaryDisplay() const { width, height } = mainScreen.size @@ -128,7 +117,6 @@ app.whenReady().then(async () => { }) startAnnouncementWatcher() - startResetApplicationWatcher() workerManager.startNetworkScannerWorker( UDP_PORT, @@ -163,7 +151,7 @@ app.on('before-quit', async () => { // Register IPC ipc-handlers function registerIPCHandlers() { - ipcMain.handle('show-alert', async (event: IpcMainInvokeEvent, message: string) => { + ipcMain.handle('show-alert', async (_event: IpcMainInvokeEvent, message: string) => { if (!windowManager) throw new Error('WindowManager is not initialized.') await windowManager.showAlert(message) }) @@ -231,4 +219,12 @@ function registerIPCHandlers() { return workerManager.startBackupRetrievalWorker(TCP_PORT, destinationPath, pathToDatabaseFile) }, ) + + ipcMain.handle( + 'start-announcement-worker', + async (_event: IpcMainInvokeEvent, message: string) => { + if (!workerManager) throw new Error('WorkerManager is not initialized.') + return workerManager.startAnnouncementWorker(pathToDatabaseFile, TCP_PORT, message) + }, + ) } diff --git a/User/src/main/preload.ts b/Desktop App/src/main/preload.ts similarity index 91% rename from User/src/main/preload.ts rename to Desktop App/src/main/preload.ts index 160a4b6..d288714 100644 --- a/User/src/main/preload.ts +++ b/Desktop App/src/main/preload.ts @@ -40,8 +40,6 @@ contextBridge.exposeInMainWorld('networkAPI', { }) contextBridge.exposeInMainWorld('uiAPI', { - startWorkers: (): Promise => ipcRenderer.invoke('start-workers'), - stopWorkers: (): Promise => ipcRenderer.invoke('stop-workers'), showAlert: (message: string): Promise => ipcRenderer.invoke('show-alert', message), changeContent: (destination: string): Promise => ipcRenderer.invoke('change-content', destination), @@ -54,3 +52,12 @@ contextBridge.exposeInMainWorld('uiAPI', { startBackupRetrieval: (destinationPath: string): Promise => ipcRenderer.invoke('start-backup-retrieval', destinationPath), }) + +contextBridge.exposeInMainWorld('workersAPI', { + startWorkers: (): Promise => ipcRenderer.invoke('start-workers'), + stopWorkers: (): Promise => ipcRenderer.invoke('stop-workers'), + startBackupRetrieval: (destinationPath: string): Promise => + ipcRenderer.invoke('start-backup-retrieval', destinationPath), + startAnnouncementWorker: (message: string): Promise => + ipcRenderer.invoke('start-announcement-worker', message), +}) diff --git a/User/src/network/connection_manager.ts b/Desktop App/src/network/connection_manager.ts similarity index 100% rename from User/src/network/connection_manager.ts rename to Desktop App/src/network/connection_manager.ts diff --git a/User/src/network/message_handler.ts b/Desktop App/src/network/message_handler.ts similarity index 100% rename from User/src/network/message_handler.ts rename to Desktop App/src/network/message_handler.ts diff --git a/User/src/network/network.ts b/Desktop App/src/network/network.ts similarity index 100% rename from User/src/network/network.ts rename to Desktop App/src/network/network.ts diff --git a/User/src/network/operation_codes.ts b/Desktop App/src/network/operation_codes.ts similarity index 97% rename from User/src/network/operation_codes.ts rename to Desktop App/src/network/operation_codes.ts index da9c980..6bb09b9 100644 --- a/User/src/network/operation_codes.ts +++ b/Desktop App/src/network/operation_codes.ts @@ -18,15 +18,16 @@ export let operationCodes = { EMAIL_VERIFICATION: 'EMAIL_VERIFICATION', FIND_BY_EMAIL: 'FIND_BY_EMAIL', + GET_USERS: 'GET_USERS', + FIND_KEY_BY_USER_ID: 'FIND_KEY_BY_USER_ID', MODIFY_USER: 'MODIFY_USER', + DELETE_USER: 'DELETE_USER', GET_DEPARTMENTS: 'GET_DEPARTMENTS', CREATE_DEPARTMENT: 'CREATE_DEPARTMENT', MODIFY_DEPARTMENT: 'MODIFY_DEPARTMENT', DELETE_DEPARTMENT: 'DELETE_DEPARTMENT', - GET_USERS: 'GET_USERS', - FIND_KEY_BY_USER_ID: 'FIND_KEY_BY_USER_ID', SEND_ANNOUNCEMENT: 'SEND_ANNOUNCEMENT', GET_USER_INFORMATION: 'GET_USER_INFORMATION', diff --git a/User/src/network/operations_base/operation_handler.ts b/Desktop App/src/network/operations_base/operation_handler.ts similarity index 100% rename from User/src/network/operations_base/operation_handler.ts rename to Desktop App/src/network/operations_base/operation_handler.ts diff --git a/User/src/network/operations_base/operation_plugin.ts b/Desktop App/src/network/operations_base/operation_plugin.ts similarity index 100% rename from User/src/network/operations_base/operation_plugin.ts rename to Desktop App/src/network/operations_base/operation_plugin.ts diff --git a/User/src/network/operations_custom/general_operations.ts b/Desktop App/src/network/operations_custom/general_operations.ts similarity index 100% rename from User/src/network/operations_custom/general_operations.ts rename to Desktop App/src/network/operations_custom/general_operations.ts diff --git a/User/src/network/operations_custom/user_to_user_operations.ts b/Desktop App/src/network/operations_custom/user_to_user_operations.ts similarity index 100% rename from User/src/network/operations_custom/user_to_user_operations.ts rename to Desktop App/src/network/operations_custom/user_to_user_operations.ts diff --git a/User/src/network/socket_communicator/socket_communicator_base.ts b/Desktop App/src/network/socket_communicator/socket_communicator_base.ts similarity index 100% rename from User/src/network/socket_communicator/socket_communicator_base.ts rename to Desktop App/src/network/socket_communicator/socket_communicator_base.ts diff --git a/User/src/network/socket_communicator/tcp_client_communicator.ts b/Desktop App/src/network/socket_communicator/tcp_client_communicator.ts similarity index 100% rename from User/src/network/socket_communicator/tcp_client_communicator.ts rename to Desktop App/src/network/socket_communicator/tcp_client_communicator.ts diff --git a/User/src/network/socket_communicator/tcp_server_communicator.ts b/Desktop App/src/network/socket_communicator/tcp_server_communicator.ts similarity index 100% rename from User/src/network/socket_communicator/tcp_server_communicator.ts rename to Desktop App/src/network/socket_communicator/tcp_server_communicator.ts diff --git a/User/src/network/socket_communicator/udp_socket_communicator.ts b/Desktop App/src/network/socket_communicator/udp_socket_communicator.ts similarity index 100% rename from User/src/network/socket_communicator/udp_socket_communicator.ts rename to Desktop App/src/network/socket_communicator/udp_socket_communicator.ts diff --git a/User/src/network/tcp/tcp_client.ts b/Desktop App/src/network/tcp/tcp_client.ts similarity index 100% rename from User/src/network/tcp/tcp_client.ts rename to Desktop App/src/network/tcp/tcp_client.ts diff --git a/User/src/network/tcp/tcp_server.ts b/Desktop App/src/network/tcp/tcp_server.ts similarity index 100% rename from User/src/network/tcp/tcp_server.ts rename to Desktop App/src/network/tcp/tcp_server.ts diff --git a/User/src/network/udp/udp_client.ts b/Desktop App/src/network/udp/udp_client.ts similarity index 100% rename from User/src/network/udp/udp_client.ts rename to Desktop App/src/network/udp/udp_client.ts diff --git a/User/src/network/udp/udp_server.ts b/Desktop App/src/network/udp/udp_server.ts similarity index 100% rename from User/src/network/udp/udp_server.ts rename to Desktop App/src/network/udp/udp_server.ts diff --git a/User/src/workers/backup_retrieval_worker.ts b/Desktop App/src/workers/backup_retrieval_worker.ts similarity index 100% rename from User/src/workers/backup_retrieval_worker.ts rename to Desktop App/src/workers/backup_retrieval_worker.ts diff --git a/User/src/workers/directories_watcher_worker.ts b/Desktop App/src/workers/directories_watcher_worker.ts similarity index 100% rename from User/src/workers/directories_watcher_worker.ts rename to Desktop App/src/workers/directories_watcher_worker.ts diff --git a/User/src/workers/network_scanner_worker.ts b/Desktop App/src/workers/network_scanner_worker.ts similarity index 100% rename from User/src/workers/network_scanner_worker.ts rename to Desktop App/src/workers/network_scanner_worker.ts diff --git a/User/src/workers/resource_coordinator_worker.ts b/Desktop App/src/workers/resource_coordinator_worker.ts similarity index 100% rename from User/src/workers/resource_coordinator_worker.ts rename to Desktop App/src/workers/resource_coordinator_worker.ts diff --git a/Desktop App/src/workers/send_announcement_worker.ts b/Desktop App/src/workers/send_announcement_worker.ts new file mode 100644 index 0000000..2c69f24 --- /dev/null +++ b/Desktop App/src/workers/send_announcement_worker.ts @@ -0,0 +1,27 @@ +import { AnnouncementSender } from '../helpers/announcement_sender' + +// Read environment variables passed by WorkerManager +const pathToDatabaseFile = process.env.DATABASE_FILE_PATH as string +const clientPort = parseInt(process.env.CLIENT_PORT as string, 10) +const message = process.env.MESSAGE as string + +if (!pathToDatabaseFile || !clientPort || !message) { + console.error('Missing necessary environment variables for AnnouncementWorker.') + process.exit(1) +} + +// Initialize the AnnouncementSender instance +const announcementSender = new AnnouncementSender(pathToDatabaseFile, clientPort) + +// Start the announcement process +announcementSender.start(message) + +// Handle graceful termination on receiving kill signals +const handleExit = async () => { + console.log('Announcement worker is shutting down gracefully...') + await announcementSender.stop() // Assuming stop() is implemented to clean up resources + process.exit(0) +} + +process.on('SIGTERM', handleExit) +process.on('SIGINT', handleExit) diff --git a/User/src/workers/servers_worker.ts b/Desktop App/src/workers/servers_worker.ts similarity index 100% rename from User/src/workers/servers_worker.ts rename to Desktop App/src/workers/servers_worker.ts diff --git a/User/tsconfig.json b/Desktop App/tsconfig.json similarity index 100% rename from User/tsconfig.json rename to Desktop App/tsconfig.json diff --git a/User/.env b/User/.env deleted file mode 100644 index abdda81..0000000 --- a/User/.env +++ /dev/null @@ -1,2 +0,0 @@ -UDP_PORT=41234 -TCP_PORT=41233 \ No newline at end of file diff --git a/User/.idea/.gitignore b/User/.idea/.gitignore deleted file mode 100644 index b58b603..0000000 --- a/User/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/User/.idea/.name b/User/.idea/.name deleted file mode 100644 index 0be4d80..0000000 --- a/User/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -login.html \ No newline at end of file diff --git a/User/.idea/encodings.xml b/User/.idea/encodings.xml deleted file mode 100644 index 31b5dc7..0000000 --- a/User/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/User/.idea/jsLibraryMappings.xml b/User/.idea/jsLibraryMappings.xml deleted file mode 100644 index d23208f..0000000 --- a/User/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/User/.idea/modules.xml b/User/.idea/modules.xml deleted file mode 100644 index 202146e..0000000 --- a/User/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/User/.idea/proiect-licenta.iml b/User/.idea/proiect-licenta.iml deleted file mode 100644 index 24643cc..0000000 --- a/User/.idea/proiect-licenta.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/User/.idea/vcs.xml b/User/.idea/vcs.xml deleted file mode 100644 index 62bd7a0..0000000 --- a/User/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file