From 7c4f2841e108560fa3a38c229388e939bc6a82a7 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sat, 27 Dec 2025 11:41:52 +0100 Subject: [PATCH 01/46] Fix: Security #5 --- server/controller/info.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js index 187d074..932621c 100644 --- a/server/controller/info.controller.js +++ b/server/controller/info.controller.js @@ -12,7 +12,7 @@ async function infoController(req, res){ /* Si pas d'url ou url invalide*/ - if (!url || !isValidUrl(url)) return res.status(400).send("❌ Invalid URL Or Missing"); + if (!url || typeof url !== "string" || !isValidUrl(url)) return res.status(400).send("❌ Invalid URL Or Missing"); logger.info(`/Info Request receive by the Info Controller. URL: ${url}`); From f31767e7e7a435a396b2f9d4e79dcb38b4fe4072 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sat, 27 Dec 2025 12:14:21 +0100 Subject: [PATCH 02/46] Fix: Error Handling Info Controller --- server/controller/info.controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js index 932621c..906cbff 100644 --- a/server/controller/info.controller.js +++ b/server/controller/info.controller.js @@ -40,7 +40,8 @@ async function infoController(req, res){ } catch (err) { - return res.status(500).send(`❌ ${err.message}`); + logger.error(`Info controller error: ${err && err.message ? err.message : err}`); + return res.status(500).send(`❌ Unable to fetch info`); } } From 12ff25cc4bbd451f24d559b003c6da7d9e0ead33 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sat, 27 Dec 2025 12:15:28 +0100 Subject: [PATCH 03/46] Fix: Error Handling Download Controller --- server/controller/download.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js index 3b820ee..97c071c 100644 --- a/server/controller/download.controller.js +++ b/server/controller/download.controller.js @@ -25,7 +25,7 @@ async function downloadController(req, res) { } catch (err) { logger.error(`Server Error in /download : ${err.message}`); - res.status(500).send(`❌ ${err.message}`); + res.status(500).send(`❌ Server Error`); } } From ae7d33847449d6322e2f588363d9c504635f570b Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 28 Dec 2025 12:40:55 +0100 Subject: [PATCH 04/46] Add: Rate Limit to front rendering. Using Components for reusability --- package-lock.json | 46 +++++++++++++++++++++++++++++++++---- package.json | 1 + server/helpers/rateLimit.js | 14 +++++++++++ server/server.js | 4 ++-- 4 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 server/helpers/rateLimit.js diff --git a/package-lock.json b/package-lock.json index dba5193..963b2e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "electron-squirrel-startup": "^1.0.1", "electron-updater": "^6.6.2", "express": "^5.1.0", + "express-rate-limit": "^8.2.1", "webidl-conversions": "^8.0.0", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" @@ -547,6 +548,7 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, + "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -568,6 +570,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -584,6 +587,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -598,6 +602,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": ">= 10.0.0" } @@ -1106,7 +1111,6 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2088,7 +2092,8 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true + "optional": true, + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2686,6 +2691,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -2706,6 +2712,7 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -2907,6 +2914,33 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express-rate-limit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.2.1.tgz", + "integrity": "sha512-PCZEIEIxqwhzw4KF0n7QF4QqruVTcF73O5kFKUnGOyjbCCgizBBiFaYpd/fnBLUMPw/BWw9OsiN7GgrNYr7j6g==", + "license": "MIT", + "dependencies": { + "ip-address": "10.0.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/express-rate-limit/node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -3547,7 +3581,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -4654,6 +4688,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -4671,6 +4706,7 @@ "dev": true, "license": "MIT", "optional": true, + "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -5511,6 +5547,7 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -5574,6 +5611,7 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -5588,6 +5626,7 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -5879,7 +5918,6 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", "license": "MIT", - "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", diff --git a/package.json b/package.json index cdf3322..da90d5f 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "electron-squirrel-startup": "^1.0.1", "electron-updater": "^6.6.2", "express": "^5.1.0", + "express-rate-limit": "^8.2.1", "webidl-conversions": "^8.0.0", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" diff --git a/server/helpers/rateLimit.js b/server/helpers/rateLimit.js new file mode 100644 index 0000000..d65336f --- /dev/null +++ b/server/helpers/rateLimit.js @@ -0,0 +1,14 @@ +const RateLimit = require("express-rate-limit"); + + +/* Rate Limite */ +const rateLimite = RateLimit({ + windowMs: 15 * 60, // 15 minutes + max: 5, // limit each IP to 100 requests per windowMs on the root path + message: "Too many requests, please try again later.", + statusCode: 429, // HTTP status code for "Too Many Requests" +}); + +module.exports = { + rateLimite +} \ No newline at end of file diff --git a/server/server.js b/server/server.js index fba428c..09c7ec7 100644 --- a/server/server.js +++ b/server/server.js @@ -5,7 +5,7 @@ const { logger, logSessionStart, logSessionEnd } = require("./logger"); const config = require("../config"); const { execFile } = require("child_process"); const { userYtDlp } = require("./helpers/path"); - +const { rateLimite } = require("./helpers/rateLimit") const app = express(); @@ -37,7 +37,7 @@ app.use(express.static(path.join(__dirname, "../public"))); app.use("/download", require("./routes/download.route")); app.use("/info", require("./routes/info.route")); -app.get("/", (req, res) => { +app.get("/", rateLimite ,(req, res) => { res.sendFile(path.join(__dirname, "../public/index.html")); }); From 008428f10a6081a12d57e5350a0bad6df4ebffc0 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 28 Dec 2025 12:47:00 +0100 Subject: [PATCH 05/46] Fix: Remove Unsued Import in Controller --- server/controller/download.controller.js | 1 - server/controller/info.controller.js | 3 --- 2 files changed, 4 deletions(-) diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js index 97c071c..597b290 100644 --- a/server/controller/download.controller.js +++ b/server/controller/download.controller.js @@ -1,7 +1,6 @@ const { fetchDownload } = require("../services/download.services"); const { logger } = require("../logger"); const { isValidUrl, isSafePath } = require("../helpers/validation"); -const { buildYtDlpArgs } = require("../helpers/buildArgs"); const { notifyDownloadFinished } = require("../helpers/notify"); const listeners = []; diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js index 906cbff..949506b 100644 --- a/server/controller/info.controller.js +++ b/server/controller/info.controller.js @@ -1,6 +1,3 @@ -const express = require("express"); -const router = express.Router(); - const { fetchInfo } = require("../services/info.services"); const { parseVideo, parsePlaylist } = require("../helpers/parseInfo"); const { logger } = require("../logger"); From 6c9d296fbd0b0f1fe9ed6e4dcc8df85c23372831 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Tue, 30 Dec 2025 11:38:18 +0100 Subject: [PATCH 06/46] Add: Some Variables in config.js. For Modules --- config.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/config.js b/config.js index e460608..a8362a8 100644 --- a/config.js +++ b/config.js @@ -7,4 +7,17 @@ module.exports = { debugMode: true, localMode: !app.isPackaged, DiscordRPCID: "1410934537051181146", + + // Variables Used to toggle main features + autoUpdate: true, + discordRPC: true, + customTopBar: true, // (Will be active on next launch) + autoDownloadPlaylist: true, + logSystem: true, // Disable = Dangerous + autoCheckInfo: true, // To Improve speed ? (NO) + outputTitleCheck: true, // For Non latin characters (Russian) + addThumbail: true, // The Pictures in the files (audio files) + addMetadata: true, // Looks Explicit + downloadSystem: true, // Why would you disable this ? I don't know but why not + notifySystem: true // Notification when download } \ No newline at end of file From 43869420c0a7735a59619ecb11dff2ba1115c489 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:04:38 +0100 Subject: [PATCH 07/46] Update: Update Script + Dependencies --- package-lock.json | 1272 ++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 579 insertions(+), 695 deletions(-) diff --git a/package-lock.json b/package-lock.json index 963b2e4..e2c08aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,9 +63,9 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.18", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", - "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", "dev": true, "license": "MIT", "dependencies": { @@ -169,88 +169,6 @@ "global-agent": "^3.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/node-gyp/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/node-gyp/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/@electron/node-gyp/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/@electron/node-gyp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@electron/notarize": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", @@ -306,9 +224,9 @@ } }, "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==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -379,21 +297,21 @@ } }, "node_modules/@electron/rebuild": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz", - "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.0.1.tgz", + "integrity": "sha512-iMGXb6Ib7H/Q3v+BKZJoETgF9g6KMNZVbsO4b7Dmpgb5qTFqyFTzqW9F3TOSHdybv2vKYKzSS9OiZL+dcJb+1Q==", "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", + "graceful-fs": "^4.2.11", + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^11.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", @@ -404,35 +322,7 @@ "electron-rebuild": "lib/cli.js" }, "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/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/@electron/rebuild/node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "node": ">=22.12.0" } }, "node_modules/@electron/rebuild/node_modules/semver": { @@ -448,24 +338,14 @@ "node": ">=10" } }, - "node_modules/@electron/rebuild/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/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.3.tgz", + "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.7", + "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", @@ -607,13 +487,6 @@ "node": ">= 10.0.0" } }, - "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/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -740,6 +613,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, "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", @@ -818,18 +704,41 @@ "node": ">= 10.0.0" } }, - "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==", + "node_modules/@npmcli/agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/fs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "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": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/fs/node_modules/semver": { @@ -845,21 +754,6 @@ "node": ">=10" } }, - "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/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -907,16 +801,6 @@ "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", @@ -975,9 +859,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz", - "integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==", + "version": "22.19.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.6.tgz", + "integrity": "sha512-qm+G8HuG6hOHQigsi7VGuLjUVu6TtBo/F05zvX04Mw2uCg9Dv0Qxy3Qw7j41SidlTcl5D/5yg0SEZqOB+EqZnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1049,11 +933,14 @@ "license": "MIT" }, "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==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, "node_modules/accepts": { "version": "2.0.0", @@ -1078,33 +965,6 @@ "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "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/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1165,52 +1025,53 @@ "license": "MIT" }, "node_modules/app-builder-lib": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz", - "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.4.0.tgz", + "integrity": "sha512-Uas6hNe99KzP3xPWxh5LGlH8kWIVjZixzmMJHNB9+6hPyDpjc7NQMkVgi16rQDdpCFy22ZU5sp8ow7tvjeMgYQ==", "dev": true, "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/asar": "3.2.18", + "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/notarize": "2.5.0", - "@electron/osx-sign": "1.3.1", - "@electron/rebuild": "3.7.0", - "@electron/universal": "2.0.1", + "@electron/osx-sign": "1.3.3", + "@electron/rebuild": "4.0.1", + "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.3.4", + "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", - "config-file-ts": "0.2.8-rc1", + "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "26.0.11", + "electron-publish": "26.3.4", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", + "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^10.0.0", + "minimatch": "^10.0.3", "plist": "3.1.0", "resedit": "^1.7.0", - "semver": "^7.3.8", + "semver": "~7.7.3", "tar": "^6.1.12", "temp-file": "^3.4.0", - "tiny-async-pool": "1.3.0" + "tiny-async-pool": "1.3.0", + "which": "^5.0.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "26.0.12", - "electron-builder-squirrel-windows": "26.0.12" + "dmg-builder": "26.4.0", + "electron-builder-squirrel-windows": "26.4.0" } }, "node_modules/app-builder-lib/node_modules/fs-extra": { @@ -1376,9 +1237,9 @@ } }, "node_modules/body-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", - "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -1387,7 +1248,7 @@ "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", - "qs": "^6.14.0", + "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" }, @@ -1400,9 +1261,9 @@ } }, "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", - "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -1478,23 +1339,22 @@ "license": "MIT" }, "node_modules/builder-util": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz", - "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==", + "version": "26.3.4", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.3.4.tgz", + "integrity": "sha512-aRn88mYMktHxzdqDMF6Ayj0rKoX+ZogJ75Ck7RrIqbY/ad0HBvnS2xA4uHfzrGr5D2aLL3vU6OBEH4p0KMV2XQ==", "dev": true, "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", "app-builder-bin": "5.0.0-alpha.12", - "builder-util-runtime": "9.3.1", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", - "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", @@ -1504,9 +1364,9 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz", - "integrity": "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.5.1.tgz", + "integrity": "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ==", "license": "MIT", "dependencies": { "debug": "^4.3.4", @@ -1564,33 +1424,27 @@ } }, "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "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", + "@npmcli/fs": "^4.0.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^10.0.1", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", "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" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/cacache/node_modules/brace-expansion": { @@ -1603,48 +1457,85 @@ "balanced-match": "^1.0.0" } }, + "node_modules/cacache/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "node_modules/cacache/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", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/cacache/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==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } + "license": "ISC" }, "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/cacheable-lookup": { @@ -1739,9 +1630,9 @@ "license": "MIT" }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, "funding": [ { @@ -1754,16 +1645,6 @@ "node": ">=8" } }, - "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/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -1959,74 +1840,6 @@ "dev": true, "license": "MIT" }, - "node_modules/config-file-ts": { - "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.3.12", - "typescript": "^5.4.3" - } - }, - "node_modules/config-file-ts/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", @@ -2110,6 +1923,29 @@ "node": ">= 8" } }, + "node_modules/cross-spawn/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/cross-spawn/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/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2292,15 +2128,14 @@ } }, "node_modules/dmg-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz", - "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.4.0.tgz", + "integrity": "sha512-ce4Ogns4VMeisIuCSK0C62umG0lFy012jd8LMZ6w/veHUeX4fqfDrGe+HTWALAEwK6JwKP+dhPvizhArSOsFbg==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.4.0", + "builder-util": "26.3.4", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -2466,19 +2301,19 @@ } }, "node_modules/electron-builder": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz", - "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.4.0.tgz", + "integrity": "sha512-FCUqvdq2AULL+Db2SUGgjOYTbrgkPxZtCjqIZGnjH9p29pTWyesQqBIfvQBKa6ewqde87aWl49n/WyI/NyUBog==", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "app-builder-lib": "26.4.0", + "builder-util": "26.3.4", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", - "dmg-builder": "26.0.12", + "ci-info": "^4.2.0", + "dmg-builder": "26.4.0", "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" @@ -2492,15 +2327,15 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", - "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.4.0.tgz", + "integrity": "sha512-7dvalY38xBzWNaoOJ4sqy2aGIEpl2S1gLPkkB0MHu1Hu5xKQ82il1mKSFlXs6fLpXUso/NmyjdHGlSHDRoG8/w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "26.0.12", - "builder-util": "26.0.11", + "app-builder-lib": "26.4.0", + "builder-util": "26.3.4", "electron-winstaller": "5.4.0" } }, @@ -2543,15 +2378,15 @@ } }, "node_modules/electron-publish": { - "version": "26.0.11", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz", - "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==", + "version": "26.3.4", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.3.4.tgz", + "integrity": "sha512-5/ouDPb73SkKuay2EXisPG60LTFTMNHWo2WLrK5GDphnWK9UC+yzYrzVeydj078Yk4WUXi0+TaaZsNd6Zt5k/A==", "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "26.0.11", - "builder-util-runtime": "9.3.1", + "builder-util": "26.3.4", + "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.0", "fs-extra": "^10.1.0", @@ -2622,18 +2457,18 @@ "license": "MIT" }, "node_modules/electron-updater": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.6.2.tgz", - "integrity": "sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==", + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.7.3.tgz", + "integrity": "sha512-EgkT8Z9noqXKbwc3u5FkJA+r48jwZ5DTUiOkJMOTEEH//n5Am6wfQGz7nvSFEA2oIAMv9jRzn5JKTyWeSKOPgg==", "license": "MIT", "dependencies": { - "builder-util-runtime": "9.3.1", + "builder-util-runtime": "9.5.1", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", - "semver": "^7.6.3", + "semver": "~7.7.3", "tiny-typed-emitter": "^2.1.0" } }, @@ -2744,6 +2579,16 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -2932,15 +2777,6 @@ "express": ">= 4.11" } }, - "node_modules/express-rate-limit/node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -2997,6 +2833,24 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", @@ -3183,16 +3037,16 @@ } }, "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==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs.realpath": { @@ -3549,16 +3403,6 @@ "node": ">= 14" } }, - "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-corefoundation": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", @@ -3581,7 +3425,7 @@ "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, + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -3621,23 +3465,6 @@ "node": ">=0.8.19" } }, - "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/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", @@ -3657,10 +3484,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "license": "MIT", "engines": { "node": ">= 12" @@ -3675,19 +3501,6 @@ "node": ">= 0.10" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "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", @@ -3708,13 +3521,6 @@ "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-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -3760,11 +3566,14 @@ } }, "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": ">=16" + } }, "node_modules/jackspeak": { "version": "3.4.3", @@ -3800,6 +3609,16 @@ "node": ">=10" } }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", @@ -3957,93 +3776,26 @@ } }, "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==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "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", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/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/make-fetch-happen/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/make-fetch-happen/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/make-fetch-happen/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/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": "^18.17.0 || >=20.5.0" } }, "node_modules/matcher": { @@ -4175,44 +3927,41 @@ } }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": ">=16 || 14 >=14.17" } }, "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==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.1.tgz", + "integrity": "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ==", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.1.6", + "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" @@ -4231,6 +3980,19 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/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-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -4244,6 +4006,19 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/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-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -4257,18 +4032,30 @@ "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==", + "node_modules/minipass-sized/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": "MIT", + "license": "ISC", "dependencies": { - "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" } }, "node_modules/mkdirp": { @@ -4309,16 +4096,16 @@ } }, "node_modules/node-abi": { - "version": "3.85.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", - "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.24.0.tgz", + "integrity": "sha512-u2EC1CeNe25uVtX3EZbdQ275c74zdZmmpzrHEQh2aIYqoVjlglfUpOX9YY85x1nlBydEKDVaSmMNhR7N82Qj8A==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "semver": "^7.6.3" }, "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/node-abi/node_modules/semver": { @@ -4384,20 +4171,95 @@ } } }, + "node_modules/node-gyp": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.5.0.tgz", + "integrity": "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "tar": "^7.4.3", + "tinyglobby": "^0.2.12", + "which": "^5.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-gyp/node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, "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==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-url": { @@ -4542,16 +4404,13 @@ } }, "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==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", + "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", "dev": true, "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -4617,16 +4476,6 @@ "dev": true, "license": "ISC" }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-to-regexp": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", @@ -4666,6 +4515,19 @@ "dev": true, "license": "ISC" }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -4712,13 +4574,13 @@ } }, "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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/progress": { @@ -4731,13 +4593,6 @@ "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", @@ -4787,9 +4642,9 @@ } }, "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -4839,9 +4694,9 @@ } }, "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", - "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -4965,20 +4820,18 @@ } }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "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", + "peer": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/roarr": { @@ -5062,10 +4915,13 @@ } }, "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", - "license": "BlueOak-1.0.0" + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } }, "node_modules/semver": { "version": "6.3.1", @@ -5324,31 +5180,18 @@ } }, "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==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/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": ">= 14" } }, "node_modules/source-map": { @@ -5381,16 +5224,16 @@ "optional": true }, "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^3.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/stack-trace": { @@ -5531,6 +5374,32 @@ "node": ">=10" } }, + "node_modules/tar/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/tar/node_modules/fs-minipass/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/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -5541,6 +5410,33 @@ "node": ">=8" } }, + "node_modules/tar/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/tar/node_modules/minizlib/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/temp": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", @@ -5619,21 +5515,6 @@ "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", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -5666,6 +5547,23 @@ "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, "node_modules/tmp": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", @@ -5748,20 +5646,6 @@ "node": ">= 0.6" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -5770,29 +5654,29 @@ "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^3.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/universalify": { @@ -5873,9 +5757,9 @@ } }, "node_modules/webidl-conversions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz", - "integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "license": "BSD-2-Clause", "engines": { "node": ">=20" @@ -5898,19 +5782,19 @@ "license": "BSD-2-Clause" }, "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { - "node-which": "bin/node-which" + "node-which": "bin/which.js" }, "engines": { - "node": ">= 8" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/winston": { diff --git a/package.json b/package.json index da90d5f..4bcfd13 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "main": "main.js", "scripts": { "start": "electron --trace-warnings .", - "dist": "electron-builder", + "build": "electron-builder", "update": "npm update" }, "dependencies": { From 42ae0e7204bc33343bc4034a276886541dea77e2 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:06:17 +0100 Subject: [PATCH 08/46] =?UTF-8?q?Feat:=20Add=20Codec=20H264=20to=20vid?= =?UTF-8?q?=C3=A9o=20output?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/helpers/buildArgs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index 6d16353..eb48215 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -17,7 +17,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { "--fragment-retries", "10", "--ffmpeg-location", ffmpegPath, "--extractor-args","youtube:player_client=default", - "--js-runtimes", `deno:${denoPath}` + "--js-runtimes", `deno:${denoPath}`, + "-S", "vcodec:h264" // Will be replaced with a variables when i will add the settings panel (Next Update ?) ]; if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3"); From 31d8b20a761c4ed693ac5bc4edc96afa70ee195b Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:03:32 +0100 Subject: [PATCH 09/46] Feat: Implement Config File. Read by Front and Back. It aims to give possibility to disable some features quickly. Currenty: DiscordRPC, AutoCheckInfo, AutoUpdate, Custom TopBar, AddMetadata, Add Thumbail were put and implement. Other need to be implement. That's the begin of Settings Panel --- config.js | 29 ++-- config/config.json | 13 ++ main.js | 15 ++- preload.js | 3 +- public/index.html | 6 +- public/script/fetchinfo.js | 262 +++++++++++++++++++----------------- public/script/topbar.js | 10 +- server/helpers/buildArgs.js | 7 +- 8 files changed, 193 insertions(+), 152 deletions(-) create mode 100644 config/config.json diff --git a/config.js b/config.js index a8362a8..0df8abb 100644 --- a/config.js +++ b/config.js @@ -1,5 +1,20 @@ const packageJson = require("./package.json"); const { app } = require("electron"); +const fs = require("fs"); +const path = require("path"); + +const featuresPath = path.join(__dirname, "./config/config.json"); + +let features = {}; + +function loadFeatures() { + const raw = fs.readFileSync(featuresPath, "utf-8"); + features = JSON.parse(raw); + console.log(features) + return features; +} + +const configFeatures = loadFeatures(); module.exports = { version: packageJson.version, @@ -7,17 +22,5 @@ module.exports = { debugMode: true, localMode: !app.isPackaged, DiscordRPCID: "1410934537051181146", - - // Variables Used to toggle main features - autoUpdate: true, - discordRPC: true, - customTopBar: true, // (Will be active on next launch) - autoDownloadPlaylist: true, - logSystem: true, // Disable = Dangerous - autoCheckInfo: true, // To Improve speed ? (NO) - outputTitleCheck: true, // For Non latin characters (Russian) - addThumbail: true, // The Pictures in the files (audio files) - addMetadata: true, // Looks Explicit - downloadSystem: true, // Why would you disable this ? I don't know but why not - notifySystem: true // Notification when download + configFeatures } \ No newline at end of file diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..f969fb6 --- /dev/null +++ b/config/config.json @@ -0,0 +1,13 @@ +{ + "autoUpdate": true, + "discordRPC": true, + "customTopBar": true, + "autoDownloadPlaylist": true, + "logSystem": true, + "autoCheckInfo": true, + "outputTitleCheck": true, + "addThumbnail": true, + "addMetadata": true, + "downloadSystem": true, + "notifySystem": true +} \ No newline at end of file diff --git a/main.js b/main.js index aa43415..b8680de 100644 --- a/main.js +++ b/main.js @@ -3,8 +3,11 @@ const { app, BrowserWindow, ipcMain, dialog, Menu, shell } = require("electron") const path = require("path"); const os = require("os"); const fs = require("fs"); + const { logger, logSessionStart, logSessionEnd, logDir } = require("./server/logger"); const { AutoUpdater } = require("./server/update.js"); +const { configFeatures } = require("./config.js"); +const { startRPC } = require("./server/discordRPC"); let mainWindow; const logsFolderPath = logDir; @@ -77,7 +80,7 @@ async function createMainWindow() { height: 800, minWidth: 750, minHeight: 800, - frame:false, + frame: !configFeatures.customTopBar, webPreferences: { nodeIntegration: false, contextIsolation: true, @@ -163,11 +166,15 @@ app.whenReady().then(async () => { await expressServer.startServer(); logger.info("Express Server Started"); - const { startRPC } = require("./server/discordRPC"); - startRPC(); + ipcMain.handle("features", () => { + return configFeatures; + }); + + configFeatures.discordRPC ? startRPC() : ""; await createMainWindow(); - AutoUpdater(mainWindow); + configFeatures.AutoUpdater ? AutoUpdater(mainWindow) : ""; // Auto Update + } catch (err) { logger.error("Window or Server error :", err); app.quit(); diff --git a/preload.js b/preload.js index 2f0e8e8..5da0c1c 100644 --- a/preload.js +++ b/preload.js @@ -3,7 +3,8 @@ const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("electronAPI", { getDefaultDownloadPath: () => ipcRenderer.invoke("get-default-download-path"), selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"), - setProgress: (percent) => ipcRenderer.send("set-progress", percent) + setProgress: (percent) => ipcRenderer.send("set-progress", percent), + getFeatures: () => ipcRenderer.invoke("features") }); // Contrôles de fenêtre et outils custom pour la topbar diff --git a/public/index.html b/public/index.html index 76d9296..3f8e077 100644 --- a/public/index.html +++ b/public/index.html @@ -17,7 +17,7 @@ -
+
@@ -31,12 +31,12 @@
-
+
-
+

Freedom Loader

diff --git a/public/script/fetchinfo.js b/public/script/fetchinfo.js index bffb928..9db3040 100644 --- a/public/script/fetchinfo.js +++ b/public/script/fetchinfo.js @@ -25,156 +25,164 @@ async function fetchVideoInfo(url) { return { error: "Network or JSON Issue" }; } } +async function init() { + const configFeatures = await window.electronAPI.getFeatures(); -document.addEventListener("DOMContentLoaded", () => { - const urlInput = document.getElementById("UrlInput"); - const infoDiv = document.getElementById("videoInfo"); - const loaderBox = document.getElementById("loaderBox"); + if (!configFeatures.autoCheckInfo) return; - let lastFetchedUrl = ""; + document.addEventListener("DOMContentLoaded", () => { + const urlInput = document.getElementById("UrlInput"); + const infoDiv = document.getElementById("videoInfo"); + const loaderBox = document.getElementById("loaderBox"); - urlInput.addEventListener("input", async () => { - const url = urlInput.value.trim(); + let lastFetchedUrl = ""; - // Si champ vide -> reset total - if (!url || url.length < 2) { - infoDiv.innerHTML = ""; - infoDiv.classList.remove("visible", "playlist-mode"); - lastFetchedUrl = ""; - return; - } + urlInput.addEventListener("input", async () => { + const url = urlInput.value.trim(); - if (url === lastFetchedUrl) return; - lastFetchedUrl = url; + // Si champ vide -> reset total + if (!url || url.length < 2) { + infoDiv.innerHTML = ""; + infoDiv.classList.remove("visible", "playlist-mode"); + lastFetchedUrl = ""; + return; + } - loaderBox.style.display = "flex"; - const data = await fetchVideoInfo(url); - loaderBox.style.display = "none"; + if (url === lastFetchedUrl) return; + lastFetchedUrl = url; - // Gestion des erreurs - if (data.error) { - infoDiv.innerHTML = ` -
- ${data.error} -
- `; - infoDiv.classList.add("visible"); - infoDiv.classList.remove("playlist-mode"); + loaderBox.style.display = "flex"; + const data = await fetchVideoInfo(url); loaderBox.style.display = "none"; - return; - } - // ---------- PLAYLIST ---------- - if (data.type === "playlist") { - infoDiv.classList.add("playlist-mode"); - infoDiv.innerHTML = ` -

Playlist Detected: ${data.title}

-

Video Count: ${data.count}

-

Channel : ${data.channel || "Unknown"}

-
- `; - - const listDiv = document.getElementById("playlistVideos"); - - data.videos.forEach(v => { - const durationStr = v.duration - ? `${Math.floor(v.duration / 60)}m ${(v.duration % 60).toString().padStart(2,"0")}s` : "Inconnue"; - - const videoUrl = v.id ? `https://www.youtube.com/watch?v=${v.id}` : v.url; - - listDiv.innerHTML += ` -
- Thumbnail -

${v.title}

-

Duration : ${durationStr}

-

URL - -

+ // Gestion des erreurs + if (data.error) { + infoDiv.innerHTML = ` +
+ ${data.error}
`; - }); + infoDiv.classList.add("visible"); + infoDiv.classList.remove("playlist-mode"); + loaderBox.style.display = "none"; + return; + } - // Gestion du bouton copier - listDiv.addEventListener("click", (event) => { - if (event.target.classList.contains("copy-btn")) { - const btn = event.target; - if (btn.disabled) return; + // ---------- PLAYLIST ---------- + if (data.type === "playlist") { + infoDiv.classList.add("playlist-mode"); + infoDiv.innerHTML = ` +

Playlist Detected: ${data.title}

+

Video Count: ${data.count}

+

Channel : ${data.channel || "Unknown"}

+
+ `; - btn.disabled = true; - const url = btn.dataset.url; - navigator.clipboard.writeText(url) - .then(() => { - const original = btn.textContent; + const listDiv = document.getElementById("playlistVideos"); - btn.style.opacity = 0; - btn.style.transform = "scale(0.7)"; + data.videos.forEach(v => { + const durationStr = v.duration + ? `${Math.floor(v.duration / 60)}m ${(v.duration % 60).toString().padStart(2,"0")}s` : "Inconnue"; - setTimeout(() => { - btn.textContent = "✅"; - btn.style.opacity = 1; - btn.style.transform = "scale(1)"; + const videoUrl = v.id ? `https://www.youtube.com/watch?v=${v.id}` : v.url; + + listDiv.innerHTML += ` +
+ Thumbnail +

${v.title}

+

Duration : ${durationStr}

+

URL + +

+
+ `; + }); + + // Gestion du bouton copier + listDiv.addEventListener("click", (event) => { + if (event.target.classList.contains("copy-btn")) { + const btn = event.target; + if (btn.disabled) return; + + btn.disabled = true; + const url = btn.dataset.url; + navigator.clipboard.writeText(url) + .then(() => { + const original = btn.textContent; + + btn.style.opacity = 0; + btn.style.transform = "scale(0.7)"; setTimeout(() => { - btn.style.opacity = 0; - btn.style.transform = "scale(0.7)"; + btn.textContent = "✅"; + btn.style.opacity = 1; + btn.style.transform = "scale(1)"; setTimeout(() => { - btn.textContent = original; - btn.style.opacity = 1; - btn.style.transform = "scale(1)"; - btn.disabled = false; - }, 300); + btn.style.opacity = 0; + btn.style.transform = "scale(0.7)"; - }, 1000); + setTimeout(() => { + btn.textContent = original; + btn.style.opacity = 1; + btn.style.transform = "scale(1)"; + btn.disabled = false; + }, 300); - }, 300); - }) - .catch(() => { - const original = btn.textContent; - btn.textContent = "❌"; - setTimeout(() => { - btn.textContent = original; - btn.disabled = false; - }, 1500); - }); - } - }); + }, 1000); + + }, 300); + }) + .catch(() => { + const original = btn.textContent; + btn.textContent = "❌"; + setTimeout(() => { + btn.textContent = original; + btn.disabled = false; + }, 1500); + }); + } + }); + + infoDiv.classList.add("visible"); + return; + } + + infoDiv.classList.remove("playlist-mode"); + + // ---------- VIDEO NORMALE ---------- + const durationStr = data.duration + ? `${Math.floor(data.duration/60)}m ${(data.duration%60).toString().padStart(2,"0")}s` + : "Unknown"; + + const sizeStr = formatSize(data.filesize_approx); + const readableDate = formatDate(data.upload_date); + const categories = data.categories?.join(", ") || "Non spécifiées"; + + infoDiv.innerHTML = ` +

${data.title}

+ Thumbnail +
    +
  • Duration : ${durationStr}
  • +
  • Uploader : ${data.uploader || "Inconnu"}
  • +
  • Upload Date : ${readableDate}
  • +
  • Views : ${data.view_count?.toLocaleString() || "?"}
  • +
  • Likes : ${data.like_count?.toLocaleString() || "?"}
  • +
  • URL : ${data.webpage_url}
  • +
  • Channel : ${data.channel_url}
  • +
  • Estimed Size : ${sizeStr}
  • +
  • Category : ${categories}
  • +
+ `; infoDiv.classList.add("visible"); - return; - } + }); - infoDiv.classList.remove("playlist-mode"); + }) - // ---------- VIDEO NORMALE ---------- - const durationStr = data.duration - ? `${Math.floor(data.duration/60)}m ${(data.duration%60).toString().padStart(2,"0")}s` - : "Unknown"; +}; - const sizeStr = formatSize(data.filesize_approx); - const readableDate = formatDate(data.upload_date); - const categories = data.categories?.join(", ") || "Non spécifiées"; - - infoDiv.innerHTML = ` -

${data.title}

- Thumbnail -
    -
  • Duration : ${durationStr}
  • -
  • Uploader : ${data.uploader || "Inconnu"}
  • -
  • Upload Date : ${readableDate}
  • -
  • Views : ${data.view_count?.toLocaleString() || "?"}
  • -
  • Likes : ${data.like_count?.toLocaleString() || "?"}
  • -
  • URL : ${data.webpage_url}
  • -
  • Channel : ${data.channel_url}
  • -
  • Estimed Size : ${sizeStr}
  • -
  • Category : ${categories}
  • -
- `; - - infoDiv.classList.add("visible"); - }); - -}) \ No newline at end of file +init(); \ No newline at end of file diff --git a/public/script/topbar.js b/public/script/topbar.js index 0225ea8..2221667 100644 --- a/public/script/topbar.js +++ b/public/script/topbar.js @@ -21,4 +21,12 @@ function setupTopbarListeners() { }); } -setupTopbarListeners(); +setupTopbarListeners(); // IF it put it the if check. It don't work. Why ? + +const features = await window.electronAPI.getFeatures(); + +if(!features.customTopBar){ + document.getElementById("topbar").style.display = "none"; + document.getElementById("container").style.marginTop = "0"; + document.getElementById("theme-switcher").style.top = "30px"; +} \ No newline at end of file diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index eb48215..16586f3 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -2,6 +2,7 @@ const path = require("path"); const getUserBrowser = require("./getBrowser"); const { ffmpegPath, denoPath} = require("./path"); +const { configFeatures } = require("../../config.js"); function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { @@ -10,8 +11,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { "--cookies-from-browser", `${getUserBrowser()}`, "--no-continue", "--no-overwrites", - "--embed-thumbnail", - "--add-metadata", + configFeatures.addThumbail ? "--embed-thumbnail" : null, + configFeatures.addMetadata ? "--add-metadata" : null, "--concurrent-fragments", "8", "--retries", "10", "--fragment-retries", "10", @@ -37,7 +38,7 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { args.push("-o", path.join(outputFolder, "%(title)s.%(ext)s")); args.push(url); - return args; + return args.filter(Boolean); } module.exports = { buildYtDlpArgs }; From b867d819b74698b3b41fcae49040268971a598f4 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:04:06 +0100 Subject: [PATCH 10/46] Fix: Increment App Version for 1.3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4bcfd13..9d34697 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "freedom-loader", "productName": "Freedom Loader", - "version": "1.3.1", + "version": "1.3.2", "author": "MasterAcnolo", "description": "Freedom Loader", "main": "main.js", From adcee623868e15f95e0be02d4301a0c3a5c44be5 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:41:55 +0100 Subject: [PATCH 11/46] Fix: ReadME Badge Version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0476cc4..29fc38d 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
- +
From 489a4766fab0f775a23501bf18b93d53fda2f6b2 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 21:47:38 +0100 Subject: [PATCH 12/46] Feat: Path Verification (Security #4) --- main.js | 29 ++++++++++++-- preload.js | 3 +- public/script/custompath.js | 75 ++++++++++++++++++++++++------------- 3 files changed, 76 insertions(+), 31 deletions(-) diff --git a/main.js b/main.js index b8680de..afe90f4 100644 --- a/main.js +++ b/main.js @@ -101,21 +101,44 @@ async function createMainWindow() { }); } +function validateDownloadPath(userPath) { + const userHome = os.homedir(); // C:\Users\ + + if (!userPath) return path.join(userHome, "Downloads", "Freedom Loader"); + + // Résolution canonique et suivi des symlinks + const resolved = fs.realpathSync(path.resolve(userPath)); + const normalizedHome = path.resolve(userHome) + path.sep; + + if (!resolved.startsWith(normalizedHome)) { + throw new Error("Chemin non autorisé : uniquement les sous-dossiers du dossier utilisateur sont permis !"); + } + + return resolved; +} + + // IPC ipcMain.handle("select-download-folder", async () => { try { const result = await dialog.showOpenDialog({ properties: ["openDirectory"] }); if (!result.canceled && result.filePaths.length > 0) { - logger.info(`Dossier sélectionné : ${result.filePaths[0]}`); - return result.filePaths[0]; + const validatedPath = validateDownloadPath(result.filePaths[0]); + logger.info(`Folder Checked and Valid : ${validatedPath}`); + return validatedPath; } return null; } catch (err) { - logger.error(`Error when creating Output Folder : ${err.message}`); + logger.error(`An Error Occured when validating folder : ${err.message}`); return null; } }); +ipcMain.handle("validate-download-path", (event, userPath) => { + return validateDownloadPath(userPath); +}); + + ipcMain.handle("get-default-download-path", () => defaultDownloadPath); ipcMain.on("set-progress", (event, percent) => { diff --git a/preload.js b/preload.js index 5da0c1c..4e5eb5f 100644 --- a/preload.js +++ b/preload.js @@ -4,7 +4,8 @@ contextBridge.exposeInMainWorld("electronAPI", { getDefaultDownloadPath: () => ipcRenderer.invoke("get-default-download-path"), selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"), setProgress: (percent) => ipcRenderer.send("set-progress", percent), - getFeatures: () => ipcRenderer.invoke("features") + getFeatures: () => ipcRenderer.invoke("features"), + getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path) }); // Contrôles de fenêtre et outils custom pour la topbar diff --git a/public/script/custompath.js b/public/script/custompath.js index 4bb81ad..ccf01f0 100644 --- a/public/script/custompath.js +++ b/public/script/custompath.js @@ -1,41 +1,62 @@ window.addEventListener("DOMContentLoaded", async () => { const savePathElem = document.getElementById("savePath"); + const form = document.getElementById("downloadForm"); - // Essayer de charger depuis le localStorage - let savedPath = localStorage.getItem("customDownloadPath"); - - // Sinon demander le chemin par défaut à l'API Electron - if (!savedPath) { - savedPath = await window.electronAPI.getDefaultDownloadPath(); - } - - // Afficher le chemin - if (savePathElem) { - savePathElem.textContent = savedPath; - } - - // Créer l'input caché s'il n'existe pas déjà + // input caché = DERNIER chemin validé par le back let hidden = document.getElementById("savePathInput"); if (!hidden) { hidden = document.createElement("input"); hidden.type = "hidden"; hidden.name = "savePath"; hidden.id = "savePathInput"; - document.getElementById("downloadForm").appendChild(hidden); + form.appendChild(hidden); } - hidden.value = savedPath; - // Gestion du bouton de modification - document.getElementById("changePath").addEventListener("click", async () => { - const selectedPath = await window.electronAPI.selectDownloadFolder(); - if (selectedPath) { - // Met à jour l'affichage - savePathElem.textContent = selectedPath; - hidden.value = selectedPath; + async function applyPathFromBack(path) { + savePathElem.textContent = path; + hidden.value = path; + localStorage.setItem("customDownloadPath", path); // UX only + } - // Et le stocke en localStorage pour la prochaine fois - localStorage.setItem("customDownloadPath", selectedPath); + async function loadInitialPath() { + // On affiche ce que le user a vu la dernière fois (UX) + const cached = localStorage.getItem("customDownloadPath"); + if (cached) { + savePathElem.textContent = cached; } - }); -}); + // MAIS la source de vérité reste le back + try { + const validatedPath = await window.electronAPI.getValidatedDownloadPath( + cached + ); + await applyPathFromBack(validatedPath); + } catch { + // fallback sûr + const defaultPath = + await window.electronAPI.getDefaultDownloadPath(); + await applyPathFromBack(defaultPath); + } + } + + await loadInitialPath(); + + document + .getElementById("changePath") + .addEventListener("click", async () => { + try { + const selectedPath = + await window.electronAPI.selectDownloadFolder(); + + if (!selectedPath) return; // annulé + + // Validation back obligatoire + const validatedPath = + await window.electronAPI.getValidatedDownloadPath(selectedPath); + + await applyPathFromBack(validatedPath); + } catch (err) { + alert("Dossier non autorisé."); + } + }); +}); From a69114edced2339e432109dc7321acc405924c93 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:49:34 +0100 Subject: [PATCH 13/46] Feat: Package Update + Add NSIS Installer Banner --- build/banner.bmp | Bin 0 -> 154542 bytes package-lock.json | 4 ++-- package.json | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 build/banner.bmp diff --git a/build/banner.bmp b/build/banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..5938b74c142ae329e74b60eb7b9097158bb67fd5 GIT binary patch literal 154542 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 G;Qs*`H}{DE literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json index e2c08aa..84cb76d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "freedom-loader", - "version": "1.3.1", + "version": "1.3.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "freedom-loader", - "version": "1.3.1", + "version": "1.3.2", "dependencies": { "chalk": "^4.1.2", "debug": "^4.4.1", diff --git a/package.json b/package.json index 9d34697..07fc418 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,10 @@ "from": "build/app-icon.ico", "to": "app-icon.ico" }, + { + "from": "build/banner.bmp", + "to": "banner.bmp" + }, { "from": "build/error.png", "to": "error.png" @@ -91,6 +95,7 @@ "allowToChangeInstallationDirectory": true, "installerIcon": "build/app-icon.ico", "uninstallerIcon": "build/uninstaller-icon.ico", + "installerSidebar": "build/banner.bmp", "createDesktopShortcut": true, "createStartMenuShortcut": true, "shortcutName": "Freedom Loader" From 745a73a5b05846a70605467d85d6ca67b43e4242 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 09:03:50 +0100 Subject: [PATCH 14/46] Feat: Add version badge controlled. Before we needed to write with the hand for the front. But now there is an IPC event that provide App Version from package.json --- main.js | 1 + preload.js | 1 + public/index.html | 3 ++- public/script/appVersion.js | 6 ++++++ 4 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 public/script/appVersion.js diff --git a/main.js b/main.js index afe90f4..c690b5e 100644 --- a/main.js +++ b/main.js @@ -16,6 +16,7 @@ const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader app.setAppUserModelId("com.masteracnolo.freedomloader"); // pour notifications Windows app.disableHardwareAcceleration(); +ipcMain.handle("version", () => config.version); // Gestion single instance const gotLock = app.requestSingleInstanceLock(); diff --git a/preload.js b/preload.js index 4e5eb5f..150ec42 100644 --- a/preload.js +++ b/preload.js @@ -5,6 +5,7 @@ contextBridge.exposeInMainWorld("electronAPI", { selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"), setProgress: (percent) => ipcRenderer.send("set-progress", percent), getFeatures: () => ipcRenderer.invoke("features"), + getVersion: () => ipcRenderer.invoke("version"), getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path) }); diff --git a/public/index.html b/public/index.html index 3f8e077..ebafd10 100644 --- a/public/index.html +++ b/public/index.html @@ -95,10 +95,11 @@
- v1.3.1 + + diff --git a/public/script/appVersion.js b/public/script/appVersion.js new file mode 100644 index 0000000..ad9aaa0 --- /dev/null +++ b/public/script/appVersion.js @@ -0,0 +1,6 @@ +async function versionLabel(){ + const appVersion = await window.electronAPI.getVersion(); + document.getElementById("version-badge").textContent = `v${appVersion}`; +}; + +versionLabel(); \ No newline at end of file From 0ff4715b3515a2bbf459fe5cb3a950d1c78a7310 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 09:28:46 +0100 Subject: [PATCH 15/46] Fix: Correct Config.json file for packaged version --- config.js | 6 ++++-- package.json | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/config.js b/config.js index 0df8abb..b4ffc4a 100644 --- a/config.js +++ b/config.js @@ -3,7 +3,9 @@ const { app } = require("electron"); const fs = require("fs"); const path = require("path"); -const featuresPath = path.join(__dirname, "./config/config.json"); +const localMode = !app.isPackaged; + +const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath, "config.json")); let features = {}; @@ -20,7 +22,7 @@ module.exports = { version: packageJson.version, applicationPort: "8787", debugMode: true, - localMode: !app.isPackaged, + localMode, DiscordRPCID: "1410934537051181146", configFeatures } \ No newline at end of file diff --git a/package.json b/package.json index 07fc418..d19f5ab 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,10 @@ { "from": "server", "to": "server" + }, + { + "from": "config/config.json", + "to": "config.json" } ], "win": { From 01b6bcd02c951c3f0fa796f6a57f213c89f12ab7 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:00:17 +0100 Subject: [PATCH 16/46] Feat: Add Newline YT-DLP Args. Add Toggle Switches for verbose, autodownloadplaylist + Fix Thumbail misspell --- config/config.json | 9 ++++++--- server/helpers/buildArgs.js | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/config/config.json b/config/config.json index f969fb6..872dfb0 100644 --- a/config/config.json +++ b/config/config.json @@ -2,12 +2,15 @@ "autoUpdate": true, "discordRPC": true, "customTopBar": true, - "autoDownloadPlaylist": true, - "logSystem": true, "autoCheckInfo": true, - "outputTitleCheck": true, "addThumbnail": true, "addMetadata": true, + "verboseLogs": false, + "autoDownloadPlaylist": true, + + + "logSystem": true, + "outputTitleCheck": true, "downloadSystem": true, "notifySystem": true } \ No newline at end of file diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index 16586f3..25c8c25 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -8,10 +8,12 @@ const { configFeatures } = require("../../config.js"); function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { const args = [ + configFeatures.verboseLogs ? "--verbose" : null, // Verbose Logs "--cookies-from-browser", `${getUserBrowser()}`, "--no-continue", "--no-overwrites", - configFeatures.addThumbail ? "--embed-thumbnail" : null, + "--newline", // YT-DLP Logs Format + configFeatures.addThumbnail ? "--embed-thumbnail" : null, configFeatures.addMetadata ? "--add-metadata" : null, "--concurrent-fragments", "8", "--retries", "10", @@ -19,7 +21,8 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { "--ffmpeg-location", ffmpegPath, "--extractor-args","youtube:player_client=default", "--js-runtimes", `deno:${denoPath}`, - "-S", "vcodec:h264" // Will be replaced with a variables when i will add the settings panel (Next Update ?) + "-S", "vcodec:h264", // Will be replaced with a variables when i will add the settings panel (Next Update ?) + configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist" ]; if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3"); From f959171db5d2be446aa26382c581bc9e1033b30d Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:57:37 +0100 Subject: [PATCH 17/46] Feat: Add CustomVideo Codec Choice with verification in config.json --- config/config.json | 1 + server/helpers/buildArgs.js | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/config/config.json b/config/config.json index 872dfb0..2fd13e9 100644 --- a/config/config.json +++ b/config/config.json @@ -7,6 +7,7 @@ "addMetadata": true, "verboseLogs": false, "autoDownloadPlaylist": true, + "customCodec": "h264", "logSystem": true, diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index 25c8c25..feae9ce 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -3,7 +3,22 @@ const path = require("path"); const getUserBrowser = require("./getBrowser"); const { ffmpegPath, denoPath} = require("./path"); const { configFeatures } = require("../../config.js"); +const { logger } = require("../logger"); +function validateCodec(codec){ + + const validCodec = [ + "av01","vp9.2", "vp9" , "h265" , "h264" , "vp8" , "h263", "theora" + ] + + if(validCodec.includes(codec)){ + logger.info("Codec Valid:", codec) + return codec + } else{ + logger.error(`Codec not valid: ${codec}. Using default codec`) + return "h264" + } +} function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { @@ -21,7 +36,7 @@ function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { "--ffmpeg-location", ffmpegPath, "--extractor-args","youtube:player_client=default", "--js-runtimes", `deno:${denoPath}`, - "-S", "vcodec:h264", // Will be replaced with a variables when i will add the settings panel (Next Update ?) + "-S", `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`, configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist" ]; From 5398fed928b7edf0bfd180254a541482a5ab16d0 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:59:45 +0100 Subject: [PATCH 18/46] Fix: Remove unusued Variable --- config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config.js b/config.js index b4ffc4a..7fa4a84 100644 --- a/config.js +++ b/config.js @@ -21,7 +21,6 @@ const configFeatures = loadFeatures(); module.exports = { version: packageJson.version, applicationPort: "8787", - debugMode: true, localMode, DiscordRPCID: "1410934537051181146", configFeatures From 163faec2213a82be1fbd64e00716692e7cac42a1 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:01:24 +0100 Subject: [PATCH 19/46] Feat: Add Configuration Button. user can edit config.json as wanted. Linked and IPC --- main.js | 10 ++++++++++ preload.js | 3 ++- public/index.html | 1 + public/script/topbar.js | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/main.js b/main.js index c690b5e..daa1923 100644 --- a/main.js +++ b/main.js @@ -11,6 +11,13 @@ const { startRPC } = require("./server/discordRPC"); let mainWindow; const logsFolderPath = logDir; + +const basePath = config.localMode + ? path.join(__dirname, "config") + : path.join(path.dirname(process.execPath), "resources"); + +const configFolderPath = path.join(basePath, "config.json"); + const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader"); app.setAppUserModelId("com.masteracnolo.freedomloader"); // pour notifications Windows @@ -176,6 +183,9 @@ ipcMain.on("open-website", () => { ipcMain.on("open-wiki", () => { shell.openExternal("https://masteracnolo.github.io/FreedomLoader/pages/wiki.html"); }); +ipcMain.on("open-config", () => { + if (configFolderPath) shell.openPath(configFolderPath); +}); // App ready diff --git a/preload.js b/preload.js index 150ec42..aacdf74 100644 --- a/preload.js +++ b/preload.js @@ -17,5 +17,6 @@ contextBridge.exposeInMainWorld("topbarAPI", { openDevTools: () => ipcRenderer.send("open-devtools"), openLogs: () => ipcRenderer.send("open-logs"), openWebsite: () => ipcRenderer.send("open-website"), - openWiki: () => ipcRenderer.send("open-wiki") + openWiki: () => ipcRenderer.send("open-wiki"), + openConfig: () => ipcRenderer.send("open-config") }); diff --git a/public/index.html b/public/index.html index ebafd10..d517673 100644 --- a/public/index.html +++ b/public/index.html @@ -23,6 +23,7 @@ +
diff --git a/public/script/topbar.js b/public/script/topbar.js index 2221667..be7f584 100644 --- a/public/script/topbar.js +++ b/public/script/topbar.js @@ -10,6 +10,7 @@ function setupTopbarListeners() { const logsBtn = document.getElementById('logs-btn'); const websiteBtn = document.getElementById('website-btn'); const wikiBtn = document.getElementById('wiki-btn'); + const configBtn = document.getElementById('config-btn'); if (minBtn) minBtn.onclick = () => topbarAPI.minimize(); if (maxBtn) maxBtn.onclick = () => topbarAPI.maximize(); @@ -18,6 +19,7 @@ function setupTopbarListeners() { if (logsBtn) logsBtn.onclick = () => topbarAPI.openLogs(); if (websiteBtn) websiteBtn.onclick = () => topbarAPI.openWebsite(); if (wikiBtn) wikiBtn.onclick = () => topbarAPI.openWiki(); + if (configBtn) configBtn.onclick = () => topbarAPI.openConfig(); }); } From 55db30febcfe8dbfdb176f64373c4c58f0f459b1 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:21:43 +0100 Subject: [PATCH 20/46] Fix: Remove Useless Console.log --- config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config.js b/config.js index 7fa4a84..730dd0b 100644 --- a/config.js +++ b/config.js @@ -12,7 +12,6 @@ let features = {}; function loadFeatures() { const raw = fs.readFileSync(featuresPath, "utf-8"); features = JSON.parse(raw); - console.log(features) return features; } From e45810b54cc55a67ebebce3d12a48965b1707301 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:22:29 +0100 Subject: [PATCH 21/46] Add: Better logs. Write logs when a download is init --- server/helpers/buildArgs.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index feae9ce..011cb8a 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -12,7 +12,7 @@ function validateCodec(codec){ ] if(validCodec.includes(codec)){ - logger.info("Codec Valid:", codec) + logger.info(`Codec Valid: ${codec}`) return codec } else{ logger.error(`Codec not valid: ${codec}. Using default codec`) @@ -21,6 +21,26 @@ function validateCodec(codec){ } function buildYtDlpArgs({ url, audioOnly, quality, outputFolder }) { + + logger.info("--- CONFIGURATION ---"); + + logger.info(`CONFIG autoUpdate: ${configFeatures.autoUpdate}`); + logger.info(`CONFIG discordRPC: ${configFeatures.discordRPC}`); + logger.info(`CONFIG customTopBar: ${configFeatures.customTopBar}`); + logger.info(`CONFIG autoCheckInfo: ${configFeatures.autoCheckInfo}`); + logger.info(`CONFIG addThumbnail: ${configFeatures.addThumbnail}`); + logger.info(`CONFIG addMetadata: ${configFeatures.addMetadata}`); + logger.info(`CONFIG verboseLogs: ${configFeatures.verboseLogs}`); + logger.info(`CONFIG autoDownloadPlaylist: ${configFeatures.autoDownloadPlaylist}`); + logger.info(`CONFIG customCodec: ${configFeatures.customCodec}`); + + // ACTIVATE THEM WHEN THE FEATURE IS IMPLEMENTED + // logger.info(`CONFIG logSystem: ${configFeatures.logSystem}`); + // logger.info(`CONFIG outputTitleCheck: ${configFeatures.outputTitleCheck}`); + // logger.info(`CONFIG downloadSystem: ${configFeatures.downloadSystem}`); + // logger.info(`CONFIG notifySystem: ${configFeatures.notifySystem}`); + + logger.info("---------------------"); const args = [ configFeatures.verboseLogs ? "--verbose" : null, // Verbose Logs From c356e2e30d626c73b7af35f9e07951930f29a14f Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:22:40 +0100 Subject: [PATCH 22/46] Fix: Using ASAR for every parts of the projects (the server is now in it) and i put the binaries in a /binaries folder. It's better for readability of the resources folder --- main.js | 11 ++++++----- package.json | 16 +++++----------- server/helpers/path.js | 15 +++++++++++---- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/main.js b/main.js index daa1923..abe30e4 100644 --- a/main.js +++ b/main.js @@ -31,10 +31,10 @@ const gotLock = app.requestSingleInstanceLock(); // Native dependencies check (yt-dlp.exe, ffmpeg.exe, ffprobe.exe, Deno) function checkNativeDependencies() { const deps = [ - { name: "yt-dlp.exe", path: path.join(process.resourcesPath, "yt-dlp.exe") }, - { name: "ffmpeg.exe", path: path.join(process.resourcesPath, "ffmpeg.exe") }, - { name: "ffprobe.exe", path: path.join(process.resourcesPath, "ffprobe.exe") }, - { name: "deno.exe", path: path.join(process.resourcesPath, "deno.exe") }, + { name: "yt-dlp.exe", path: path.join(process.resourcesPath, "binaries","yt-dlp.exe") }, + { name: "ffmpeg.exe", path: path.join(process.resourcesPath, "binaries", "ffmpeg.exe") }, + { name: "ffprobe.exe", path: path.join(process.resourcesPath, "binaries", "ffprobe.exe") }, + { name: "deno.exe", path: path.join(process.resourcesPath, "binaries", "deno.exe") }, ]; const missing = deps.filter(dep => !fs.existsSync(dep.path)); let errorMsg = ""; @@ -193,7 +193,8 @@ app.whenReady().then(async () => { logSessionStart(); logger.info("App Ready, Server Express starting..."); - const serverPath = path.join(__dirname, "server", "server.js"); + const serverPath = path.join(__dirname, "server", "server.js") + const expressServer = require(serverPath); try { diff --git a/package.json b/package.json index d19f5ab..5c430a8 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,7 @@ "files": [ "**/*", "node_modules/**/*", - "!logs/*.json", - "server/**/*", - "server/node_modules/**/*" + "!logs/*.json" ], "directories": { "buildResources": "build" @@ -66,23 +64,19 @@ }, { "from": "ressources/yt-dlp.exe", - "to": "yt-dlp.exe" + "to": "binaries/yt-dlp.exe" }, { "from": "ressources/ffmpeg.exe", - "to": "ffmpeg.exe" + "to": "binaries/ffmpeg.exe" }, { "from": "ressources/ffprobe.exe", - "to": "ffprobe.exe" + "to": "binaries/ffprobe.exe" }, { "from": "ressources/deno.exe", - "to": "deno.exe" - }, - { - "from": "server", - "to": "server" + "to": "binaries/deno.exe" }, { "from": "config/config.json", diff --git a/server/helpers/path.js b/server/helpers/path.js index d045c44..bf35f94 100644 --- a/server/helpers/path.js +++ b/server/helpers/path.js @@ -3,6 +3,8 @@ const fs = require("fs"); const { app } = require("electron"); const config = require("../../config"); +const { logger } = require("../logger.js"); + let userYtDlp; let ffmpegPath; let denoPath; @@ -11,16 +13,21 @@ const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe"); if (config.localMode) { userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe"); - ffmpegPath = path.join(__dirname, "../../ressources"); // <- contient ffmpeg.exe et ffprobe.exe + ffmpegPath = path.join(__dirname, "../../ressources/"); // <- contient ffmpeg.exe et ffprobe.exe denoPath = path.join(__dirname, "../../ressources/deno.exe"); } else { - userYtDlp = path.join(app.getPath("userData"), "yt-dlp.exe"); - ffmpegPath = path.join(process.resourcesPath, "ffmpeg.exe"); - denoPath = path.join(process.resourcesPath, "deno.exe"); + userYtDlp = path.join(app.getPath("userData"),"binaries","yt-dlp.exe"); + ffmpegPath = path.join(process.resourcesPath, "binaries","ffmpeg.exe"); + denoPath = path.join(process.resourcesPath, "binaries","deno.exe"); if (!fs.existsSync(userYtDlp)) { fs.copyFileSync(sourceYtDlp, userYtDlp); } + } +if (!userYtDlp){ logger.error("Missing YT-DLP")} +if (!ffmpegPath){ logger.error("Missing FFMPEG")} +if (!denoPath){ logger.error("Missing DENO")} + module.exports = { userYtDlp, ffmpegPath, denoPath }; From 65364d3095a321c95b7a2c12ca9e96e5f8927b8f Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:22:57 +0100 Subject: [PATCH 23/46] Fix: Update Dependencies --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 84cb76d..04606d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -859,9 +859,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.19.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.6.tgz", - "integrity": "sha512-qm+G8HuG6hOHQigsi7VGuLjUVu6TtBo/F05zvX04Mw2uCg9Dv0Qxy3Qw7j41SidlTcl5D/5yg0SEZqOB+EqZnQ==", + "version": "22.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "dev": true, "license": "MIT", "dependencies": { From b7a193b062379b1518adfe7a0b5ebf0144ede8c0 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:23:26 +0100 Subject: [PATCH 24/46] Fix: Remove unusued import server.js --- server/server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/server.js b/server/server.js index 09c7ec7..e8f1f75 100644 --- a/server/server.js +++ b/server/server.js @@ -1,7 +1,7 @@ const express = require("express"); const fs = require("fs"); const path = require("path"); -const { logger, logSessionStart, logSessionEnd } = require("./logger"); +const { logger, logSessionEnd } = require("./logger"); const config = require("../config"); const { execFile } = require("child_process"); const { userYtDlp } = require("./helpers/path"); From 2f105f51457552c905e92dca3e85bb6b5caf3c74 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:01:26 +0100 Subject: [PATCH 25/46] Fix: Put config.json file into config folder for better readability + Fix Yt-DLP Path --- config.js | 2 +- main.js | 4 ++-- package.json | 2 +- server/helpers/path.js | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config.js b/config.js index 730dd0b..928349d 100644 --- a/config.js +++ b/config.js @@ -5,7 +5,7 @@ const path = require("path"); const localMode = !app.isPackaged; -const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath, "config.json")); +const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath,"config/" ,"config.json")); let features = {}; diff --git a/main.js b/main.js index abe30e4..272a9c5 100644 --- a/main.js +++ b/main.js @@ -13,10 +13,10 @@ let mainWindow; const logsFolderPath = logDir; const basePath = config.localMode - ? path.join(__dirname, "config") + ? path.join(__dirname ) : path.join(path.dirname(process.execPath), "resources"); -const configFolderPath = path.join(basePath, "config.json"); +const configFolderPath = path.join(basePath, "config" ,"config.json"); const defaultDownloadPath = path.join(os.homedir(), "Downloads", "Freedom Loader"); diff --git a/package.json b/package.json index 5c430a8..f2084d2 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ }, { "from": "config/config.json", - "to": "config.json" + "to": "config/config.json" } ], "win": { diff --git a/server/helpers/path.js b/server/helpers/path.js index bf35f94..8eac1a5 100644 --- a/server/helpers/path.js +++ b/server/helpers/path.js @@ -9,14 +9,14 @@ let userYtDlp; let ffmpegPath; let denoPath; -const sourceYtDlp = path.join(process.resourcesPath, "yt-dlp.exe"); +const sourceYtDlp = path.join(process.resourcesPath, "binaries","yt-dlp.exe"); if (config.localMode) { userYtDlp = path.join(__dirname, "../../ressources/yt-dlp.exe"); ffmpegPath = path.join(__dirname, "../../ressources/"); // <- contient ffmpeg.exe et ffprobe.exe denoPath = path.join(__dirname, "../../ressources/deno.exe"); } else { - userYtDlp = path.join(app.getPath("userData"),"binaries","yt-dlp.exe"); + userYtDlp = path.join(app.getPath("userData"),"yt-dlp.exe"); ffmpegPath = path.join(process.resourcesPath, "binaries","ffmpeg.exe"); denoPath = path.join(process.resourcesPath, "binaries","deno.exe"); From d4c33bcf2d98f688b0983e3cf91d711db2cc617d Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 15 Jan 2026 22:54:40 +0100 Subject: [PATCH 26/46] FIx: Updated Appliction Version because i did too much work to be a "minor release" --- README.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 29fc38d..44432ae 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@
- +
diff --git a/package-lock.json b/package-lock.json index 04606d8..27d3a4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "freedom-loader", - "version": "1.3.2", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "freedom-loader", - "version": "1.3.2", + "version": "1.4.0", "dependencies": { "chalk": "^4.1.2", "debug": "^4.4.1", diff --git a/package.json b/package.json index f2084d2..57f7f32 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "freedom-loader", "productName": "Freedom Loader", - "version": "1.3.2", + "version": "1.4.0", "author": "MasterAcnolo", "description": "Freedom Loader", "main": "main.js", From 0e48ab3b4c59cc0db37011914e370921cde87e57 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Fri, 16 Jan 2026 09:42:09 +0100 Subject: [PATCH 27/46] Fix: Default Theme Info Color --- public/styles/theme/default-theme.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/styles/theme/default-theme.css b/public/styles/theme/default-theme.css index a3d2017..6694dc1 100644 --- a/public/styles/theme/default-theme.css +++ b/public/styles/theme/default-theme.css @@ -29,8 +29,8 @@ --infos-box-color: #0c0140; --video-info-text-color: #ffffff; --video-info-heading-color: #007bff; - --video-info-list-color: #444444; - --video-info-list-strong-color: #000000; + --video-info-list-color: #cccccc; + --video-info-list-strong-color: #e6e6e6; --video-info-link-color: #007bff; --video-info-link-hover-color: #0056b3; From 8f0f31041dea675ea2806fbd30d1648ed572e119 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Fri, 16 Jan 2026 09:42:32 +0100 Subject: [PATCH 28/46] Fix: Remove Unusued Dependencies --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 57f7f32..795caca 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "chalk": "^4.1.2", "debug": "^4.4.1", "discord-rpc": "^4.0.1", - "electron-squirrel-startup": "^1.0.1", "electron-updater": "^6.6.2", "express": "^5.1.0", "express-rate-limit": "^8.2.1", From 5c62ed081a2fd7b842c76de237f2c14ccc4ba9c6 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 18 Jan 2026 11:28:27 +0100 Subject: [PATCH 29/46] Fix: Update ReadME Banner Redirection --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 44432ae..ddde13c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@
- Banner - + style="width: 50%;;"/>
From fecb123d0e489409d4de0bcdc4d4b08ebd7c3688 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 18 Jan 2026 13:51:17 +0100 Subject: [PATCH 30/46] Fix: Indent Index.html --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index d517673..da15ac5 100644 --- a/public/index.html +++ b/public/index.html @@ -35,7 +35,7 @@
-
+
From 45ae5d7f9844316f4cad8440d0121e4644db8a36 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 18 Jan 2026 14:09:41 +0100 Subject: [PATCH 31/46] Fix: Update Dependencies --- package-lock.json | 71 ++++++++++------------------------------------- 1 file changed, 14 insertions(+), 57 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27d3a4c..1f7d0b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "chalk": "^4.1.2", "debug": "^4.4.1", "discord-rpc": "^4.0.1", - "electron-squirrel-startup": "^1.0.1", "electron-updater": "^6.6.2", "express": "^5.1.0", "express-rate-limit": "^8.2.1", @@ -428,7 +427,6 @@ "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -450,7 +448,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -467,7 +464,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -482,7 +478,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10.0.0" } @@ -971,6 +966,7 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1512,9 +1508,9 @@ } }, "node_modules/cacache/node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.3.tgz", + "integrity": "sha512-ENg5JUHUm2rDD7IvKNFGzyElLXNjachNLp6RaGf4+JOgxXHkqA+gq81ZAMCUmtMtqBsoU62lcp6S27g1LCYGGQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -1905,8 +1901,7 @@ "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -2432,30 +2427,6 @@ "node": ">= 10.0.0" } }, - "node_modules/electron-squirrel-startup": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/electron-squirrel-startup/-/electron-squirrel-startup-1.0.1.tgz", - "integrity": "sha512-sTfFIHGku+7PsHLJ7v0dRcZNkALrV+YEozINTW8X1nM//e5O3L+rfYuvSW00lmGHnYmUjARZulD8F2V8ISI9RA==", - "license": "Apache-2.0", - "dependencies": { - "debug": "^2.2.0" - } - }, - "node_modules/electron-squirrel-startup/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/electron-squirrel-startup/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/electron-updater": { "version": "6.7.3", "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.7.3.tgz", @@ -2526,7 +2497,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -2547,7 +2517,6 @@ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -2579,16 +2548,6 @@ "node": ">= 0.8" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -2721,6 +2680,7 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", + "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -4096,9 +4056,9 @@ } }, "node_modules/node-abi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.24.0.tgz", - "integrity": "sha512-u2EC1CeNe25uVtX3EZbdQ275c74zdZmmpzrHEQh2aIYqoVjlglfUpOX9YY85x1nlBydEKDVaSmMNhR7N82Qj8A==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.25.0.tgz", + "integrity": "sha512-BRrQZc23ljOLms7EXVds3MOpB59/x7gaORodNuIwt96JKlflUmrOgv5hSJZEEM/WkW3uXpjZ4x1wcFu8V9mTpw==", "dev": true, "license": "MIT", "dependencies": { @@ -4220,9 +4180,9 @@ } }, "node_modules/node-gyp/node_modules/tar": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", - "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.3.tgz", + "integrity": "sha512-ENg5JUHUm2rDD7IvKNFGzyElLXNjachNLp6RaGf4+JOgxXHkqA+gq81ZAMCUmtMtqBsoU62lcp6S27g1LCYGGQ==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -4521,6 +4481,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -4550,7 +4511,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -4568,7 +4528,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } @@ -4826,7 +4785,6 @@ "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -5443,7 +5401,6 @@ "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -5507,7 +5464,6 @@ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -5802,6 +5758,7 @@ "resolved": "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz", "integrity": "sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA==", "license": "MIT", + "peer": true, "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.8", From 1a61972750da79a19188d9f3a032fd0c0a085eeb Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 18 Jan 2026 14:11:01 +0100 Subject: [PATCH 32/46] Add: Settings Icon --- public/assets/icon/settings.png | Bin 0 -> 28600 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/assets/icon/settings.png diff --git a/public/assets/icon/settings.png b/public/assets/icon/settings.png new file mode 100644 index 0000000000000000000000000000000000000000..848e6b11df1aa9f0c85d9f2a4ebb2a88fbee8420 GIT binary patch literal 28600 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%0A&bJCYCyVmr?t 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 literal 0 HcmV?d00001 From fef4f6de36dc4259fadb12ddf2ac89d716e885d6 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Sun, 18 Jan 2026 14:23:17 +0100 Subject: [PATCH 33/46] Sync: Synchro Settings Panel --- public/index.html | 12 +++++++++- public/script/settingsPanel.js | 7 ++++++ public/styles/layout/settingsPanel.css | 33 ++++++++++++++++++++++++++ public/styles/styles.css | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 public/script/settingsPanel.js create mode 100644 public/styles/layout/settingsPanel.css diff --git a/public/index.html b/public/index.html index da15ac5..f4bfa4f 100644 --- a/public/index.html +++ b/public/index.html @@ -32,11 +32,20 @@
-
+ + + + +
@@ -100,6 +109,7 @@ + diff --git a/public/script/settingsPanel.js b/public/script/settingsPanel.js new file mode 100644 index 0000000..6868501 --- /dev/null +++ b/public/script/settingsPanel.js @@ -0,0 +1,7 @@ +const settingsButton = document.getElementById("settings-button") +const settingsPanel = document.getElementById("settings-panel") + +function openPanel(){ + settingsPanel.style.display = "block"; + console.log("Click") +} \ No newline at end of file diff --git a/public/styles/layout/settingsPanel.css b/public/styles/layout/settingsPanel.css new file mode 100644 index 0000000..59a234e --- /dev/null +++ b/public/styles/layout/settingsPanel.css @@ -0,0 +1,33 @@ +.settings-button{ + display:flex; + background-color: rgba(219, 219, 219, 0.89); + border-radius: 12px; + padding: 5px; + transition: all ease-in-out 0.2s; + position: absolute; + top: 60px; + right: 40px; + border: none; +} + +.settings-button img{ + width: 50px; + height: 50px; +} + +.settings-button:hover{ + transform: scale(1.2); + cursor: pointer; +} + +.settings-button:active{ + transform: scale(0.9); +} + +.settings-panel{ + position: absolute; + width: 100%; + height: 100%; + background-color: red; + z-index: 9999999; +} \ No newline at end of file diff --git a/public/styles/styles.css b/public/styles/styles.css index 6472249..06bab5a 100644 --- a/public/styles/styles.css +++ b/public/styles/styles.css @@ -1,5 +1,6 @@ /* Layout */ @import url("layout/form.css"); +@import url("layout/settingsPanel.css"); @import url("layout/container.css"); @import url("layout/header.css"); @import url("layout/videoinfo.css"); From 343dbb26a2fc73703e0f34c058badc2518646575 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Tue, 20 Jan 2026 22:28:53 +0100 Subject: [PATCH 34/46] Feat: Settings Panel --- main.js | 16 ++ preload.js | 1 + public/assets/icon/settings.png | Bin 28600 -> 0 bytes public/assets/icon/settings.svg | 2 + public/index.html | 171 +++++++++++++++++- public/script/settingsPanel.js | 55 +++++- public/styles/layout/settingsPanel.css | 241 +++++++++++++++++++++++-- public/styles/variables.css | 10 + 8 files changed, 460 insertions(+), 36 deletions(-) delete mode 100644 public/assets/icon/settings.png create mode 100644 public/assets/icon/settings.svg diff --git a/main.js b/main.js index 272a9c5..1dced18 100644 --- a/main.js +++ b/main.js @@ -204,6 +204,22 @@ app.whenReady().then(async () => { ipcMain.handle("features", () => { return configFeatures; }); + + ipcMain.handle("set-feature", (event, { key, value }) => { + try { + // update mémoire + configFeatures[key] = value; + + // écriture directe sur le JSON + fs.writeFileSync(configFolderPath, JSON.stringify(configFeatures, null, 2), "utf-8"); + + logger.info(`Feature updated: ${key} = ${value}`); + return true; + } catch (err) { + logger.error(`set-feature failed (${key}): ${err.message}`); + return false; + } + }); configFeatures.discordRPC ? startRPC() : ""; diff --git a/preload.js b/preload.js index aacdf74..e9ca875 100644 --- a/preload.js +++ b/preload.js @@ -5,6 +5,7 @@ contextBridge.exposeInMainWorld("electronAPI", { selectDownloadFolder: () => ipcRenderer.invoke("select-download-folder"), setProgress: (percent) => ipcRenderer.send("set-progress", percent), getFeatures: () => ipcRenderer.invoke("features"), + setFeature: (key, value) => ipcRenderer.invoke("set-feature", { key, value }), getVersion: () => ipcRenderer.invoke("version"), getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path) }); diff --git a/public/assets/icon/settings.png b/public/assets/icon/settings.png deleted file mode 100644 index 848e6b11df1aa9f0c85d9f2a4ebb2a88fbee8420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28600 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%0A&bJCYCyVmr?t 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 diff --git a/public/assets/icon/settings.svg b/public/assets/icon/settings.svg new file mode 100644 index 0000000..39ab649 --- /dev/null +++ b/public/assets/icon/settings.svg @@ -0,0 +1,2 @@ + +ionicons-v5-q \ No newline at end of file diff --git a/public/index.html b/public/index.html index f4bfa4f..7050fe2 100644 --- a/public/index.html +++ b/public/index.html @@ -23,7 +23,6 @@ -
@@ -31,18 +30,167 @@
- - - + - From 29ca2ea4962dd133d4b9899880d3b68206488ae8 Mon Sep 17 00:00:00 2001 From: MasterAcnolo <68693319+MasterAcnolo@users.noreply.github.com> Date: Thu, 22 Jan 2026 21:39:07 +0100 Subject: [PATCH 46/46] Fix: Auto Update mispelling (Am a monkey) --- main.js | 2 +- server/update.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index e8a3a07..3bc0439 100644 --- a/main.js +++ b/main.js @@ -251,7 +251,7 @@ app.whenReady().then(async () => { configFeatures.discordRPC ? startRPC() : ""; await createMainWindow(); - configFeatures.AutoUpdater ? AutoUpdater(mainWindow) : ""; // Auto Update + configFeatures.autoUpdate ? AutoUpdater(mainWindow) : ""; // Auto Update } catch (err) { logger.error("Window or Server error :", err); diff --git a/server/update.js b/server/update.js index a21908e..d38aa70 100644 --- a/server/update.js +++ b/server/update.js @@ -1,5 +1,5 @@ const { autoUpdater } = require("electron-updater"); -const { app, Notification } = require("electron"); +const { app, Notification, shell} = require("electron"); const { logger } = require("./logger"); function AutoUpdater() {