diff --git a/README.md b/README.md index 0476cc4..ddde13c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@
- Banner - + style="width: 50%;;"/>
- +
diff --git a/build/banner.bmp b/build/banner.bmp new file mode 100644 index 0000000..5938b74 Binary files /dev/null and b/build/banner.bmp differ diff --git a/config.js b/config.js index e460608..928349d 100644 --- a/config.js +++ b/config.js @@ -1,10 +1,26 @@ const packageJson = require("./package.json"); const { app } = require("electron"); +const fs = require("fs"); +const path = require("path"); + +const localMode = !app.isPackaged; + +const featuresPath = localMode ? path.join(__dirname, "./config/config.json") : path.join(path.join(process.resourcesPath,"config/" ,"config.json")); + +let features = {}; + +function loadFeatures() { + const raw = fs.readFileSync(featuresPath, "utf-8"); + features = JSON.parse(raw); + return features; +} + +const configFeatures = loadFeatures(); 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/config/config.json b/config/config.json new file mode 100644 index 0000000..d73ef86 --- /dev/null +++ b/config/config.json @@ -0,0 +1,15 @@ +{ + "autoUpdate": true, + "discordRPC": true, + "customTopBar": true, + "autoCheckInfo": true, + "addThumbnail": true, + "addMetadata": true, + "verboseLogs": false, + "autoDownloadPlaylist": true, + "customCodec": "h264", + "logSystem": true, + "outputTitleCheck": true, + "downloadSystem": true, + "notifySystem": true +} \ No newline at end of file diff --git a/main.js b/main.js index aa43415..3bc0439 100644 --- a/main.js +++ b/main.js @@ -3,16 +3,27 @@ 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; + +const basePath = config.localMode + ? path.join(__dirname ) + : path.join(path.dirname(process.execPath), "resources"); + +const configFolderPath = path.join(basePath, "config" ,"config.json"); + 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(); @@ -20,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 = ""; @@ -77,7 +88,7 @@ async function createMainWindow() { height: 800, minWidth: 750, minHeight: 800, - frame:false, + frame: !configFeatures.customTopBar, webPreferences: { nodeIntegration: false, contextIsolation: true, @@ -98,21 +109,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) => { @@ -149,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 @@ -156,18 +193,66 @@ 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 { await expressServer.startServer(); logger.info("Express Server Started"); - const { startRPC } = require("./server/discordRPC"); - startRPC(); + ipcMain.handle("features", () => { + return configFeatures; + }); + + const featureWhitelist = new Set([ + "autoUpdate", + "discordRPC", + "customTopBar", + "autoCheckInfo", + "addThumbnail", + "addMetadata", + "verboseLogs", + "autoDownloadPlaylist", + "customCodec" + ]); + + + ipcMain.handle("set-feature", (event, { key, value }) => { + try { + if (!featureWhitelist.has(key)) { + logger.warn(`Rejected feature (not whitelisted): ${key}`); + return false; + } + + // optionnel mais propre + if (configFeatures[key] === value) { + return true; + } + + configFeatures[key] = value; + + 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() : ""; await createMainWindow(); - AutoUpdater(mainWindow); + configFeatures.autoUpdate ? AutoUpdater(mainWindow) : ""; // Auto Update + } catch (err) { logger.error("Window or Server error :", err); app.quit(); diff --git a/package-lock.json b/package-lock.json index dba5193..1f7d0b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "freedom-loader", - "version": "1.3.1", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "freedom-loader", - "version": "1.3.1", + "version": "1.4.0", "dependencies": { "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", "webidl-conversions": "^8.0.0", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" @@ -62,9 +62,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": { @@ -168,88 +168,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", @@ -305,9 +223,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": { @@ -378,21 +296,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", @@ -403,35 +321,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": { @@ -447,24 +337,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", @@ -602,13 +482,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", @@ -735,6 +608,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", @@ -813,18 +699,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": { @@ -840,21 +749,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", @@ -902,16 +796,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", @@ -970,9 +854,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.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", "dev": true, "license": "MIT", "dependencies": { @@ -1044,11 +928,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", @@ -1073,33 +960,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", @@ -1161,52 +1021,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": { @@ -1372,9 +1233,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", @@ -1383,7 +1244,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" }, @@ -1396,9 +1257,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" @@ -1474,23 +1335,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", @@ -1500,9 +1360,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", @@ -1560,33 +1420,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": { @@ -1599,48 +1453,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.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": { + "@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": { @@ -1735,9 +1626,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": [ { @@ -1750,16 +1641,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", @@ -1955,74 +1836,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", @@ -2105,6 +1918,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", @@ -2287,15 +2123,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" @@ -2461,19 +2296,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" @@ -2487,15 +2322,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" } }, @@ -2538,15 +2373,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", @@ -2592,43 +2427,19 @@ "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.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" } }, @@ -2869,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", @@ -2907,6 +2719,24 @@ "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/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -2963,6 +2793,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", @@ -3149,16 +2997,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": { @@ -3515,16 +3363,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", @@ -3587,23 +3425,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", @@ -3623,10 +3444,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" @@ -3641,19 +3461,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", @@ -3674,13 +3481,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", @@ -3726,11 +3526,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", @@ -3766,6 +3569,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", @@ -3923,93 +3736,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": { @@ -4141,44 +3887,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" @@ -4197,6 +3940,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", @@ -4210,6 +3966,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", @@ -4223,18 +3992,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": { @@ -4275,16 +4056,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.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": { - "semver": "^7.3.5" + "semver": "^7.6.3" }, "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/node-abi/node_modules/semver": { @@ -4350,20 +4131,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.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": { + "@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": { @@ -4508,16 +4364,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" @@ -4583,16 +4436,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", @@ -4632,6 +4475,20 @@ "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", + "peer": true, + "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", @@ -4676,13 +4533,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": { @@ -4695,13 +4552,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", @@ -4751,9 +4601,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" @@ -4803,9 +4653,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" @@ -4929,9 +4779,9 @@ } }, "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", @@ -4940,9 +4790,6 @@ }, "bin": { "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/roarr": { @@ -5026,10 +4873,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", @@ -5288,31 +5138,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": { @@ -5345,16 +5182,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": { @@ -5495,6 +5332,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", @@ -5505,6 +5368,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", @@ -5581,20 +5471,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", - "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", @@ -5627,6 +5503,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", @@ -5709,20 +5602,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", @@ -5731,29 +5610,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": { @@ -5834,9 +5713,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" @@ -5859,19 +5738,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 cdf3322..795caca 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,22 @@ { "name": "freedom-loader", "productName": "Freedom Loader", - "version": "1.3.1", + "version": "1.4.0", "author": "MasterAcnolo", "description": "Freedom Loader", "main": "main.js", "scripts": { "start": "electron --trace-warnings .", - "dist": "electron-builder", + "build": "electron-builder", "update": "npm update" }, "dependencies": { "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", "webidl-conversions": "^8.0.0", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0" @@ -38,9 +38,7 @@ "files": [ "**/*", "node_modules/**/*", - "!logs/*.json", - "server/**/*", - "server/node_modules/**/*" + "!logs/*.json" ], "directories": { "buildResources": "build" @@ -55,29 +53,33 @@ "from": "build/app-icon.ico", "to": "app-icon.ico" }, + { + "from": "build/banner.bmp", + "to": "banner.bmp" + }, { "from": "build/error.png", "to": "error.png" }, { "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" + "to": "binaries/deno.exe" }, { - "from": "server", - "to": "server" + "from": "config/config.json", + "to": "config/config.json" } ], "win": { @@ -90,6 +92,7 @@ "allowToChangeInstallationDirectory": true, "installerIcon": "build/app-icon.ico", "uninstallerIcon": "build/uninstaller-icon.ico", + "installerSidebar": "build/banner.bmp", "createDesktopShortcut": true, "createStartMenuShortcut": true, "shortcutName": "Freedom Loader" diff --git a/preload.js b/preload.js index 2f0e8e8..e9ca875 100644 --- a/preload.js +++ b/preload.js @@ -3,7 +3,11 @@ 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"), + setFeature: (key, value) => ipcRenderer.invoke("set-feature", { key, value }), + getVersion: () => ipcRenderer.invoke("version"), + getValidatedDownloadPath: (path) => ipcRenderer.invoke("validate-download-path", path) }); // Contrôles de fenêtre et outils custom pour la topbar @@ -14,5 +18,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 76d9296..2304b0d 100644 --- a/public/index.html +++ b/public/index.html @@ -17,7 +17,7 @@ -
+
@@ -30,13 +30,175 @@
+ + + + +
+
+ + + +
+

SETTINGS

+

Changes are saved automatically.
Somes changes could need a restart

+
+ + +
+

Basic Settings

+ +
+
+
+ Thème + + +
+ Choose the theme of the application +
+
+ + +
+ +
+ Discord RPC + Enable/disable Discord Rich Presence for your app. +
+
+ +
+ +
+ Download Playlist automatically? + If enabled, playlists will download without confirmation. +
+
+ + + +
+ +
+ Custom Top bar + Use this if the topbar is missing or you prefer a custom one. +
+
+ +
+ +
+ Auto Fetch Info + Automatically fetch information for new downloads. +
+
+
+ + + +
+ Advanced Settings + +
+ +
+ Auto Update + Enable automatic app updates. +
+
+ + + +
+ +
+ Add Metadata + Include metadata in downloaded files. +
+
+ +
+ +
+ Add Thumbnail + Include thumbnails in downloaded files. +
+
+ +
+
+ Custom Codec + + Choose your preferred video codec. +
+
+ +
+ + +
+ Developer Settings + + + + + +
+ +
+ Verbose Logs + Show verbose logs for debugging purposes. +
+
+ +
+ + + -
- -
- -
+
+ +

Freedom Loader

@@ -95,10 +257,15 @@
- v1.3.1 + + +

Because Why Not ?

+ + + 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 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é."); + } + }); +}); diff --git a/public/script/customthemes.js b/public/script/customthemes.js index 34b5ec0..129a7e7 100644 --- a/public/script/customthemes.js +++ b/public/script/customthemes.js @@ -1,8 +1,7 @@ const themes = { - default: { label: "Default", subtitle: "Because why not?" }, dark: { label: "Sombre", subtitle: "Darkness is my ally" }, light: { label: "Clair", subtitle: "Qui aime ce thème ?" }, - neon: { label: "Néon", subtitle: "How was your day ?"}, + neon: { label: "Purple", subtitle: "How was your day ?"}, nf: { label: "NF", subtitle: "You call it music, i call it my Therapist" }, songbird: { label: "Songbird", subtitle: "From Her to Eternity" }, drift: { label: "Drift", subtitle: "Si la route t'appelle, contre appel" }, diff --git a/public/script/fetchinfo.js b/public/script/fetchinfo.js index bffb928..af9c9b7 100644 --- a/public/script/fetchinfo.js +++ b/public/script/fetchinfo.js @@ -26,155 +26,166 @@ async function fetchVideoInfo(url) { } } -document.addEventListener("DOMContentLoaded", () => { - const urlInput = document.getElementById("UrlInput"); - const infoDiv = document.getElementById("videoInfo"); - const loaderBox = document.getElementById("loaderBox"); - let lastFetchedUrl = ""; +async function init() { - urlInput.addEventListener("input", async () => { - const url = urlInput.value.trim(); + document.addEventListener("DOMContentLoaded", () => { + const urlInput = document.getElementById("UrlInput"); + const infoDiv = document.getElementById("videoInfo"); + const loaderBox = document.getElementById("loaderBox"); - // Si champ vide -> reset total - if (!url || url.length < 2) { - infoDiv.innerHTML = ""; - infoDiv.classList.remove("visible", "playlist-mode"); - lastFetchedUrl = ""; - return; - } + let lastFetchedUrl = ""; - if (url === lastFetchedUrl) return; - lastFetchedUrl = url; + urlInput.addEventListener("input", async () => { - loaderBox.style.display = "flex"; - const data = await fetchVideoInfo(url); - loaderBox.style.display = "none"; + const configFeatures = await window.electronAPI.getFeatures(); + if (!configFeatures.autoCheckInfo) return; - // Gestion des erreurs - if (data.error) { - infoDiv.innerHTML = ` -
- ${data.error} -
- `; - infoDiv.classList.add("visible"); - infoDiv.classList.remove("playlist-mode"); + const url = urlInput.value.trim(); + + // Si champ vide -> reset total + if (!url || url.length < 2) { + infoDiv.innerHTML = ""; + infoDiv.classList.remove("visible", "playlist-mode"); + lastFetchedUrl = ""; + return; + } + + if (url === lastFetchedUrl) return; + lastFetchedUrl = url; + + 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/settingsPanel.js b/public/script/settingsPanel.js new file mode 100644 index 0000000..ae8f2f9 --- /dev/null +++ b/public/script/settingsPanel.js @@ -0,0 +1,50 @@ +const settingsPanel = document.getElementById("settings-panel"); +const settingsModal = document.querySelector(".settings-modal"); + +const settingsButton = document.getElementById("settings-button"); + +let isOpen = false; + +settingsButton.addEventListener("click", () => { + const isOpen = settingsPanel.style.display === "block"; + settingsPanel.style.display = isOpen ? "none" : "block"; +}); + +function closePanel() { + isOpen = false; + settingsPanel.style.display = "none"; +} + +// charge les features +async function loadSettings() { + const features = await window.electronAPI.getFeatures(); + + document.querySelectorAll(".settings-section input, .settings-section select").forEach(el => { + const key = el.dataset.key; + if (features[key] !== undefined) { + if (el.type === "checkbox") el.checked = features[key]; + else if (el.tagName === "SELECT") el.value = features[key]; + } + + el.addEventListener("change", () => { + let value = el.type === "checkbox" ? el.checked : el.value; + window.electronAPI.setFeature(key, value); + }); + }); +} + +// ouvrir le JSON +document.getElementById("open-json-btn").addEventListener("click", () => { + window.topbarAPI.openConfig(); // ton IPC existant +}); + + +/* clic sur l'overlay = fermer */ +settingsPanel.addEventListener("click", closePanel); + +/* clic dans la modal = stop propagation */ +settingsModal.addEventListener("click", (e) => { + e.stopPropagation(); +}); + +loadSettings(); diff --git a/public/script/topbar.js b/public/script/topbar.js index 0225ea8..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,7 +19,16 @@ 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(); }); } -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/public/styles/components/themebutton.css b/public/styles/components/themebutton.css deleted file mode 100644 index 3031696..0000000 --- a/public/styles/components/themebutton.css +++ /dev/null @@ -1,38 +0,0 @@ -.theme-switcher { - position: absolute; - top: 60px; - right: 10px; - background: #242424; - padding: 8px 12px; - border-radius: 8px; - color: #fff; - font-family: sans-serif; - font-size: 0.9rem; - display: flex; - align-items: center; - gap: 8px; - z-index: 1050; -} - -.theme-switcher label { - cursor: pointer; - font-weight: 600; -} - -.theme-switcher select { - background: #fff; - border: 1px solid #242424; - border-radius: 6px; - padding: 4px 8px; - color: #000; - cursor: pointer; - font-weight: 600; - transition: background 0.3s ease, color 0.3s ease; -} - -.theme-switcher select:hover, -.theme-switcher select:focus { - background: #474747; - color: #fff; - outline: none; -} diff --git a/public/styles/layout/settingsPanel.css b/public/styles/layout/settingsPanel.css new file mode 100644 index 0000000..0fa7b3d --- /dev/null +++ b/public/styles/layout/settingsPanel.css @@ -0,0 +1,234 @@ +/* SETTINGS BUTTON */ +.settings-button { + display: flex; + align-items: center; + justify-content: center; + position: fixed; + top: 60px; + right: 20px; + opacity: 0.8; + background-color: var(--settings-button-bg-color); + border-radius: 14px; + padding: 8px; + border: none; + box-shadow: 0 6px 16px rgba(0,0,0,0.25); + transition: transform 0.15s ease, box-shadow 0.15s ease; +} + +.settings-button svg { + width: 40px; + height: 40px; + stroke: var(--settings-button-text-color); +} + +.settings-button:hover { + transform: scale(1.1); + cursor: pointer; + box-shadow: 0 10px 24px rgba(0,0,0,0.35); +} + +.settings-button:active { + transform: scale(0.95); +} + + +/* SETTINGS PANEL */ +.settings-panel { + position: fixed; + top: 60px; + right: 40px; + width: 40vw; + max-width: 320px; + max-height: 80vh; + background-color: var(--settings-bg-primary-color); + border-radius: 12px; + padding: 20px; + box-shadow: 0 8px 24px rgba(0,0,0,0.4); + display: none; + overflow-y: auto; + z-index: 9999; + animation: slideIn 0.2s ease-out; + color: var(--settings-text-color); +} + +.settings-panel::-webkit-scrollbar { + width: 0px; + background: transparent; +} + +.settings-modal { + width: 100%; + min-height: auto; + max-height: none; + padding: 0; + background: none; + box-shadow: none; + border-radius: none; + +} + +/* TITLE */ +.settings-title { + margin-bottom: 20px; +} + +.settings-title h2 { + margin: 0; + font-size: 24px; +} + +.settings-title p { + font-size: 14px; + color: #ccc; + margin-top: 4px; +} + +/* SECTION */ +.settings-section { + display: flex; + flex-direction: column; + margin-bottom: 20px; + padding: 10px 15px; + background: var(--settings-bg-secondary-color); + border-radius: 12px; + gap: 6px; +} + +.settings-section h3 { + margin: 0 0 10px 0; + font-size: 18px; +} + +/* SETTING ITEM */ +.setting-item { + display: flex; + align-items: flex-start; + gap: 12px; + margin-bottom: 8px; + margin-top: 8px; +} + +.setting-item input[type="checkbox"] { + margin: 0; + flex-shrink: 0; + width: 20px; + height: 20px; +} + +.setting-info { + display: flex; + flex-direction: column; +} + +.setting-title { + font-size: 14px; + font-weight: 500; +} + +.setting-info small { + font-size: 12px; + color: var(--settings-subtitle-color); + margin-top: 2px; + font-style: italic; +} + +#theme .settings-title{ + display: flex; +} + +.setting-item select { + width: 70%; + background: #fff; + border: 1px solid #242424; + border-radius: 6px; + padding: 4px 8px; + color: #000; + cursor: pointer; + font-weight: 600; + transition: background 0.3s ease, color 0.3s ease; +} + +.setting-item select:hover, +.setting-item select:focus { + background: #474747; + color: #fff; + outline: none; +} + +/* SELECT */ +.settings-section select { + margin-left: 10px; +} + +/* DETAILS / DROPDOWN */ +details { + margin-bottom: 20px; + padding: 10px 15px; + background: #2a2a2a; + border-radius: 12px; +} + +details[open] { + box-shadow: 0 4px 15px rgba(0,0,0,0.3); +} + +details summary { + cursor: pointer; +} + +/* FOOTER */ +.settings-footer { + margin-top: 20px; + display: flex; + flex-direction: column; + gap: 10px; +} + +#open-json-btn { + padding: 6px 12px; + border-radius: 8px; + border: none; + cursor: pointer; + font-weight: 600; + background-color: var(--form-button-bg-color); + color: #fff; +} + +#experimental-args { + width: 100%; + min-height: 80px; + background-color: #1e1e1e; + border-radius: 8px; + padding: 8px; + color: #fff; + border: 1px solid #333; + resize: vertical; +} + +/* CLOSE BTN */ +.close-btn { + position: absolute; + top: 20px; + right: 20px; + background: none; + border: none; + color: white; + font-size: 24px; + cursor: pointer; + opacity: 0.6; +} + +.close-btn:hover { + opacity: 1; +} + +/* ANIMATION */ +@keyframes popIn { + from { transform: scale(0.95); opacity: 0; } + to { transform: scale(1); opacity: 1; } +} + +@keyframes slideIn { + from { transform: translateX(20px); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} \ No newline at end of file diff --git a/public/styles/styles.css b/public/styles/styles.css index 6472249..2a4aa3e 100644 --- a/public/styles/styles.css +++ b/public/styles/styles.css @@ -1,12 +1,12 @@ /* 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"); /* Components */ @import url("components/checkbox.css"); -@import url("components/themebutton.css"); @import url("components/loader.css"); @import url("theme/themeimport.css"); @@ -49,6 +49,16 @@ body { } +/* Because why not */ +#reference{ + position: fixed; + pointer-events: none; + bottom:0vh; + left: 10px; + font-size: 1em; + color: #b0b0b02f; +} + /* Scrollbar globale pour Chromium/Electron */ body::-webkit-scrollbar { width: 10px; diff --git a/public/styles/theme/chirac-theme.css b/public/styles/theme/chirac-theme.css index daee9f3..2645be5 100644 --- a/public/styles/theme/chirac-theme.css +++ b/public/styles/theme/chirac-theme.css @@ -42,6 +42,16 @@ body.chirac { /* Playlist Color */ --playlist-background-color: #d1d1d1ca; + + /* Settings */ + --settings-button-bg-color: #00196a; + --settings-button-text-color: #dcdcdc; + + --settings-bg-primary-color: #0b0528; + --settings-bg-secondary-color: #1c1055; + + --settings-text-color: #cecece; + --settings-subtitle-color: #adadad; } diff --git a/public/styles/theme/dark-theme.css b/public/styles/theme/dark-theme.css index b259c33..e1bd48f 100644 --- a/public/styles/theme/dark-theme.css +++ b/public/styles/theme/dark-theme.css @@ -36,4 +36,14 @@ body.dark { /* Playlist Color */ --playlist-background-color: #303030; + + /* Settings */ + --settings-button-bg-color: #1e1e1e; + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: #1e1e1e; + --settings-bg-secondary-color: #2a2a2a; + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #aaa; + } diff --git a/public/styles/theme/default-theme.css b/public/styles/theme/default-theme.css deleted file mode 100644 index a3d2017..0000000 --- a/public/styles/theme/default-theme.css +++ /dev/null @@ -1,43 +0,0 @@ -:root { - /* Couleurs générales */ - --background-color: #001224; /* body background bleu nuit */ - --default-text-color: #eee; /* texte clair principal */ - --subtitle-color: #007bff; /* sous-titres, header p */ - --mp3-text-color: #000000; /* couleur texte checkbox inline */ - - /* Formulaire */ - --form-bg-color: #ffffff; /* fond du formulaire */ - --form-input-bg-color: #f9f9f9; /* fond inputs */ - --form-input-border-color: #cccccc; /* bordure inputs */ - --form-input-border-focus-color: #0056b3; /* bordure focus */ - --form-input-text-color: #333333; /* texte inputs */ - --form-input-placeholder-color: #aaaaaa; /* placeholder */ - --form-button-bg-color: #007bff; /* bouton bg */ - --form-button-text-color: #ffffff; /* texte bouton */ - --form-button-bg-hover-color: #0056b3; /* bouton hover */ - - /* Checkbox */ - --checkbox-bg-default: #cccccc; - --checkbox-bg-checked: #3B82F6; - --checkbox-checkmark-border-color: #E0E0E2; - --checkbox-pulse-color: rgba(59, 130, 246, 0.5); - - /* Download status */ - --download-status-color: #007bff; - - /* Video Info Box */ - --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-link-color: #007bff; - --video-info-link-hover-color: #0056b3; - - /* Playlist Color */ - --playlist-background-color: #070823a3; -} - -body.default .download-path #savePath { - color: #ffffff; -} \ No newline at end of file diff --git a/public/styles/theme/drift-theme.css b/public/styles/theme/drift-theme.css index 9d318a7..f55f365 100644 --- a/public/styles/theme/drift-theme.css +++ b/public/styles/theme/drift-theme.css @@ -42,7 +42,17 @@ body.drift { /* Playlist Color */ --playlist-background-color: #424b5cc2; - } + + /* Settings */ + --settings-button-bg-color: #1e222ace; + --settings-button-text-color: #b3b3b4; + + --settings-bg-primary-color: #1e222a; + --settings-bg-secondary-color: #272d38; + + --settings-text-color: #bababa; + --settings-subtitle-color: #cacaca; +} diff --git a/public/styles/theme/fanatic-theme.css b/public/styles/theme/fanatic-theme.css index 3f8ff0c..401fd67 100644 --- a/public/styles/theme/fanatic-theme.css +++ b/public/styles/theme/fanatic-theme.css @@ -36,4 +36,14 @@ body.fanatic{ /* Playlist Color */ --playlist-background-color: #2b2b2b; + + /* Settings */ + --settings-button-bg-color: #1e1e1e; + --settings-button-text-color: #dcdcdc; + + --settings-bg-primary-color: #1e1e1e; + --settings-bg-secondary-color: #2d2d2d; + + --settings-text-color: #cecece; + --settings-subtitle-color: #adadad; } diff --git a/public/styles/theme/light-theme.css b/public/styles/theme/light-theme.css index 862f47d..4b1d2b1 100644 --- a/public/styles/theme/light-theme.css +++ b/public/styles/theme/light-theme.css @@ -36,4 +36,13 @@ body.light { /* Playlist Color */ --playlist-background-color: #c5c5c5b2; + + /* Settings */ + --settings-button-bg-color: #e4e4e4; + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: #cbcbcb; + --settings-bg-secondary-color: #cbcbcb; + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #656565; } diff --git a/public/styles/theme/neon-theme.css b/public/styles/theme/neon-theme.css index 987cd83..63c87da 100644 --- a/public/styles/theme/neon-theme.css +++ b/public/styles/theme/neon-theme.css @@ -43,6 +43,15 @@ body.neon { /* Playlist Color */ --playlist-background-color: #3e3e64; + + /* Settings */ + --settings-button-bg-color: #202038; + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: #242454; + --settings-bg-secondary-color: #2f2f6f; + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #d2d2d2; } body.neon .download-path { diff --git a/public/styles/theme/nf-theme.css b/public/styles/theme/nf-theme.css index 65b086a..5b7ac42 100644 --- a/public/styles/theme/nf-theme.css +++ b/public/styles/theme/nf-theme.css @@ -42,6 +42,15 @@ body.nf { /* Playlist Color */ --playlist-background-color: #4f4f4f; + + /* Settings */ + --settings-button-bg-color: #2a2a2a; + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: #2a2a2a; + --settings-bg-secondary-color: #313131; + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #7a7979; } body.nf .download-path { diff --git a/public/styles/theme/songbird-theme.css b/public/styles/theme/songbird-theme.css index 3eaaab3..976d0cc 100644 --- a/public/styles/theme/songbird-theme.css +++ b/public/styles/theme/songbird-theme.css @@ -42,6 +42,15 @@ body.songbird { /* Playlist Color */ --playlist-background-color: #3f0000; + + /* Settings */ + --settings-button-bg-color: rgba(29, 0, 0, 0.784); + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: #121212; + --settings-bg-secondary-color: #1a1a1a; + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #7a7979; } body.cyberpunk .download-path { diff --git a/public/styles/theme/spicy-theme.css b/public/styles/theme/spicy-theme.css index 3866a59..a001407 100644 --- a/public/styles/theme/spicy-theme.css +++ b/public/styles/theme/spicy-theme.css @@ -36,6 +36,17 @@ body.spicy { /* Playlist Color */ --playlist-background-color: #353232; + + /* Settings */ + --settings-button-bg-color: #1a1a1a; + --settings-button-text-color: #dcdcdc; + + --settings-bg-primary-color: #1a1a1a; + --settings-bg-secondary-color: #292929; + + --settings-text-color: #cecece; + --settings-subtitle-color: #adadad; + } /* Optionnel: background piments */ diff --git a/public/styles/theme/themeimport.css b/public/styles/theme/themeimport.css index eb320a6..7de5d07 100644 --- a/public/styles/theme/themeimport.css +++ b/public/styles/theme/themeimport.css @@ -1,6 +1,5 @@ @import url("chirac-theme.css"); @import url("dark-theme.css"); -@import url("default-theme.css"); @import url("fanatic-theme.css"); @import url("light-theme.css"); @import url("nf-theme.css"); diff --git a/public/styles/variables.css b/public/styles/variables.css index cfbb85d..29362d3 100644 --- a/public/styles/variables.css +++ b/public/styles/variables.css @@ -33,4 +33,14 @@ --video-info-list-strong-color: #000000; --video-info-link-color: #007bff; --video-info-link-hover-color: #0056b3; + + /* Settings */ + --settings-button-bg-color: var(--form-bg-color); + --settings-button-text-color: var(--default-text-color); + + --settings-bg-primary-color: var(--form-bg-color); + --settings-bg-secondary-color: var(--form-bg-color); + --settings-text-color: var(--default-text-color); + --settings-subtitle-color: #aaa; + } diff --git a/server/controller/download.controller.js b/server/controller/download.controller.js index 3b820ee..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 = []; @@ -25,7 +24,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`); } } diff --git a/server/controller/info.controller.js b/server/controller/info.controller.js index 187d074..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"); @@ -12,7 +9,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}`); @@ -40,7 +37,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`); } } diff --git a/server/helpers/buildArgs.js b/server/helpers/buildArgs.js index 6d16353..bdabf95 100644 --- a/server/helpers/buildArgs.js +++ b/server/helpers/buildArgs.js @@ -2,22 +2,64 @@ 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 }) { + + 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 "--cookies-from-browser", `${getUserBrowser()}`, "--no-continue", "--no-overwrites", - "--embed-thumbnail", - "--add-metadata", + "--newline", // YT-DLP Logs Format + configFeatures.addThumbnail ? "--embed-thumbnail" : null, + configFeatures.addMetadata ? "--add-metadata" : null, "--concurrent-fragments", "8", "--retries", "10", "--fragment-retries", "10", "--ffmpeg-location", ffmpegPath, "--extractor-args","youtube:player_client=default", - "--js-runtimes", `deno:${denoPath}` + "--js-runtimes", `deno:${denoPath}`, + "-S", + `vcodec:${validateCodec(configFeatures.customCodec) || "h264"}`+ + `,acodec:aac`, + configFeatures.autoDownloadPlaylist ? "--yes-playlist" : "--no-playlist" ]; if (audioOnly) args.push("-f", "bestaudio", "--extract-audio", "--audio-format", "mp3"); @@ -36,7 +78,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 }; diff --git a/server/helpers/path.js b/server/helpers/path.js index d045c44..8eac1a5 100644 --- a/server/helpers/path.js +++ b/server/helpers/path.js @@ -3,24 +3,31 @@ const fs = require("fs"); const { app } = require("electron"); const config = require("../../config"); +const { logger } = require("../logger.js"); + 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 + 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"),"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 }; 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..e8f1f75 100644 --- a/server/server.js +++ b/server/server.js @@ -1,11 +1,11 @@ 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"); - +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")); }); 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() {