From e40874cf7f82f383bee535e9b1c5e7d51b98e451 Mon Sep 17 00:00:00 2001 From: satori Date: Sat, 11 Jul 2026 00:36:27 -0700 Subject: [PATCH 1/2] Modernize Perplexity wrapper v1.1 --- .github/workflows/ci.yml | 22 + CHANGELOG.md | 11 + CONTRIBUTING.md | 3 + PRIVACY.md | 7 + README.md | 119 +- app.config.js | 50 +- icons/icon.png => assets/icon-source.png | Bin build.sh | 69 +- build/icons/128x128.png | Bin 0 -> 6468 bytes build/icons/16x16.png | Bin 0 -> 1029 bytes build/icons/24x24.png | Bin 0 -> 1438 bytes build/icons/256x256.png | Bin 0 -> 14387 bytes build/icons/32x32.png | Bin 0 -> 1761 bytes build/icons/48x48.png | Bin 0 -> 2386 bytes build/icons/512x512.png | Bin 0 -> 9374 bytes build/icons/64x64.png | Bin 0 -> 3011 bytes build/icons/96x96.png | Bin 0 -> 4568 bytes install.sh | 155 +- new-app.sh | 69 - package-lock.json | 3595 ++++++++++++++++++++++ package.json | 44 +- scripts/generate-icons.sh | 18 + scripts/validate-config.js | 12 + src/main.js | 170 +- src/policy.js | 134 + test/policy.test.js | 38 + test/uninstall.test.js | 44 + uninstall.sh | 47 +- 28 files changed, 4189 insertions(+), 418 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 PRIVACY.md rename icons/icon.png => assets/icon-source.png (100%) create mode 100644 build/icons/128x128.png create mode 100644 build/icons/16x16.png create mode 100644 build/icons/24x24.png create mode 100644 build/icons/256x256.png create mode 100644 build/icons/32x32.png create mode 100644 build/icons/48x48.png create mode 100644 build/icons/512x512.png create mode 100644 build/icons/64x64.png create mode 100644 build/icons/96x96.png delete mode 100755 new-app.sh create mode 100644 package-lock.json create mode 100755 scripts/generate-icons.sh create mode 100644 scripts/validate-config.js create mode 100644 src/policy.js create mode 100644 test/policy.test.js create mode 100644 test/uninstall.test.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..43bf6c3 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,22 @@ +name: CI +on: + push: + branches: [master] + pull_request: +permissions: + contents: read +jobs: + validate-template: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run check + - run: npm test + - run: bash -n build.sh install.sh uninstall.sh new-app.sh scripts/generate-icons.sh + - run: npm audit --audit-level=high + - run: ./build.sh diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..99258c1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,11 @@ +# Changelog + +## v1.1.0 — 2026-07-11 + +- Updated from Electron 31 to exact Electron 43.1.0 and electron-builder 26.15.3. +- Added sandboxing, default-deny permissions, safe navigation/auth windows, external-link validation, hostname audit mode, locked builds, tests, CI, multi-size icons, atomic install, checksums, and profile purge. +- Added prominent privacy documentation and honest Chromium limitations. + +## v1.0.0 + +- Initial Perplexity Computer wrapper. Superseded because its Electron runtime is unsupported. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ddce6ce --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +Run npm ci, npm run check, npm test, bash -n on all shell scripts, npm audit --audit-level=high, and ./build.sh. Review authentication, uploads/downloads, navigation policy, privacy claims, and KDE identity before release. diff --git a/PRIVACY.md b/PRIVACY.md new file mode 100644 index 0000000..c8d2ac5 --- /dev/null +++ b/PRIVACY.md @@ -0,0 +1,7 @@ +# Privacy and Network Behavior + +The wrapper adds no AAHA analytics. It disables Chromium component updates, background networking, domain-reliability reporting, Breakpad, Translate, Optimization Hints, Media Router, and Secure DNS; known Google update/telemetry hosts are blocked. + +Perplexity must still contact perplexity.ai, CDNs, model/search infrastructure, authentication providers, connectors, and linked sources. Google or Apple traffic may occur when the user deliberately selects those sign-in methods. Blocklists reduce known optional traffic but are not proof of zero third-party traffic. + +The local profile at ~/.config/Perplexity contains cookies, sessions, cache, local storage, and preferences. Normal uninstall preserves it; --purge removes it and signs the wrapper out without deleting the Perplexity account. diff --git a/README.md b/README.md index a86859f..8b82c22 100644 --- a/README.md +++ b/README.md @@ -1,118 +1,15 @@ -# Perplexity (AAHA) +# Perplexity for Linux — AAHA -A native **Perplexity desktop app for Linux**, built with Electron by -**Adam And His Agents (AAHA)**. It wraps the official Perplexity web app -(`https://www.perplexity.ai`) in a clean, standalone window that behaves -like a real desktop application — including a **stable taskbar icon that -KDE Plasma on Wayland will NOT swap for the generic browser icon**. +Unofficial Perplexity Electron desktop app for Fedora KDE, with a stable Wayland taskbar icon. -> **Unofficial / not affiliated with Perplexity AI, Inc.** This is a -> third-party wrapper. It is not endorsed by or affiliated with Perplexity. -> "Perplexity" and the Perplexity logo are trademarks of Perplexity AI, -> Inc. See `NOTICE` for details. Your use of Perplexity remains subject -> to Perplexity's own Terms of Service. +## Privacy notice ---- +This app uses Electron, which is Chromium-based. It disables unnecessary Chromium background services and adds no AAHA telemetry, but Perplexity, its CDNs, identity providers, connectors, and selected external sources still receive required traffic. Safeguards cannot make Chromium completely Google-free or independently auditable. See PRIVACY.md. -## Why this exists +## Install from source -KDE on Wayland picks an app's panel icon from the window's `app_id` -(WM class) and matches it to a `.desktop` file. Chromium-based PWAs all -share Chromium's identity, so KDE falls back to the generic browser icon. +Run chmod +x on the shell scripts, then ./build.sh and ./install.sh. The app installs under ~/MyApps/perplexity-aaha/app. Normal uninstall preserves ~/.config/Perplexity; ./uninstall.sh --purge removes that local profile. -A real Electron app sets its **own** `app_id` (`app.setName()` + `--class`) -and ships a `.desktop` file whose `StartupWMClass` matches exactly. KDE -finds a unique match, so your icon sticks. +AAHA_NETWORK_AUDIT=1 prints first-seen hostnames. External citations open in the system browser. File upload, drag-and-drop, and downloads remain available. ---- - -## Requirements (Fedora / KDE example) - -Node.js + npm, plus FUSE for running AppImages: - -```bash -sudo dnf install nodejs npm fuse fuse-libs -``` - -(On Debian/Ubuntu: `sudo apt install nodejs npm libfuse2`.) - ---- - -## Build & install - -From the project folder: - -```bash -chmod +x *.sh # one time, make scripts executable -./build.sh # installs deps, builds dist/ (first run downloads Electron, ~150MB) -./install.sh # registers icon + .desktop with your desktop environment -``` - -Then open your app launcher, search "Perplexity", launch it, and pin it -to your taskbar/panel. The icon stays. - -Build outputs: -- `dist/linux-unpacked/` — the native unpacked app (what `install.sh` wires up) -- `dist/*.AppImage` — a portable single-file version - -To remove it later: `./uninstall.sh` - ---- - -## Configuration (`app.config.js`) - -| Field | Value | -|-------------------------|--------------------------------------------------| -| `url` | `https://www.perplexity.ai` | -| `name` | `Perplexity` | -| `wmClass` | `Perplexity` | -| `appId` | `com.adamandhisagents.perplexity` | -| `allowedHosts` | `["perplexity.ai", "pplx.ai"]` | -| `disableHardening` | `false` (privacy hardening ON) | - -> `build.sh` syncs `app.config.js` and `icons/icon.png` into `src/` -> before building so they get packed into the app bundle (`app.asar`). - ---- - -## Privacy hardening (on by default) - -This app launches with Chromium background/phone-home subsystems disabled: -`disable-background-networking`, `disable-domain-reliability`, -`disable-component-update`, `disable-features=NetworkTimeServiceQuerying, -Translate,OptimizationHints,MediaRouter`, and `disable-breakpad`. The app -should only talk to Perplexity. To opt out, set `disableHardening: true` in -`app.config.js`. - -Verify with: - -```bash -sudo tcpdump -n -i any 'port 53 or port 443' | grep -Ei 'google|gstatic|gvt|1e100' -``` - -Note: if the wrapped site itself loads Google Fonts/reCAPTCHA/Analytics, -that is the site's own traffic and would occur in any browser too. - ---- - -## Notes / gotchas - -- **Disk:** each app bundles its own Electron runtime (~150–250 MB). -- **Single instance:** clicking the icon focuses the existing window. -- **No menu bar:** the app launches chrome-less. Remove - `Menu.setApplicationMenu(null)` in `src/main.js` if you want one. -- **Session data** lives in `~/.config/Perplexity/`, NOT in the project - folder. Your login is never committed to git or shipped in the AppImage. -- **Updates:** the bundled Electron does not auto-update. To refresh: - `npm install electron@latest --save-dev` then rebuild. - ---- - -## License - -Copyright 2026 **Adam And His Agents (AAHA)**. - -The wrapper/launcher code in this repository is licensed under the -**Apache License, Version 2.0** — see `LICENSE`. This license applies only -to the code authored here; it does not cover Perplexity, Perplexity's -software/service, or Perplexity's trademarks and logos. See `NOTICE`. +This project is unofficial and is not affiliated with Perplexity. diff --git a/app.config.js b/app.config.js index 2d9dfba..21a96f4 100644 --- a/app.config.js +++ b/app.config.js @@ -1,40 +1,16 @@ -// ============================================================ -// APP CONFIG — This is the ONLY file you edit per app. -// Change these values, swap the icon in icons/, rebuild. -// ============================================================ +"use strict"; module.exports = { - // The web app you want to wrap: + schemaVersion: 2, configured: true, + repoName: "perplexity-aaha", productName: "Perplexity", + appId: "com.adamandhisagents.perplexity", executable: "perplexity-aaha", + iconName: "perplexity-aaha", profileName: "Perplexity", + legacyProfileNames: [], compatibilityDesktopIds: ["perplexity"], url: "https://www.perplexity.ai", - - // Display name (shows in title bar, launcher, panel tooltip): - name: "Perplexity", - - // Wayland/X11 window identity. MUST match productName in package.json - // and StartupWMClass in the .desktop file so KDE keeps your icon. - wmClass: "Perplexity", - - // Reverse-DNS app id — unique per app. - appId: "com.adamandhisagents.perplexity", - - // Initial window size: - width: 1280, - height: 800, - - // Open external links (e.g. links that leave the app's domain) - // in your real browser instead of inside the app window: - openExternalInBrowser: true, - - // Restrict in-app navigation to these host suffixes. Anything else - // opens in the external browser. Perplexity uses both perplexity.ai - // and pplx.ai (short-links), so both are kept in-app. - allowedHosts: ["perplexity.ai", "pplx.ai"], - - // Optional custom user-agent. Leave null for Electron's default. - userAgent: null, - - // PRIVACY HARDENING (default: ON). Disables Chromium's background - // networking, domain-reliability beacons, component updates, network-time - // queries, translate, optimization hints, and crash metrics, so the app - // only talks to Perplexity. Set to true only if something breaks. - disableHardening: false + trustedNavigationHosts: ["perplexity.ai", "pplx.ai"], + trustedAuthHosts: ["accounts.google.com", "appleid.apple.com"], + permissions: { "clipboard-sanitized-write": ["perplexity.ai"] }, + blockedHosts: ["clients2.google.com", "clients4.google.com", "update.googleapis.com", "safebrowsing.googleapis.com", "optimizationguide-pa.googleapis.com", "redirector.gvt1.com", "google-analytics.com", "www.google-analytics.com", "stats.g.doubleclick.net"], + externalProtocols: ["http:", "https:", "mailto:"], openExternalLinks: true, + width: 1360, height: 860, category: "Network;", + comment: "Perplexity AI answer engine", keywords: "ai;search;research;perplexity;" }; diff --git a/icons/icon.png b/assets/icon-source.png similarity index 100% rename from icons/icon.png rename to assets/icon-source.png diff --git a/build.sh b/build.sh index 771c797..8aa56fa 100755 --- a/build.sh +++ b/build.sh @@ -1,58 +1,19 @@ #!/usr/bin/env bash -# Build the Electron app into an unpacked native dir + AppImage. -# app.config.js is the SINGLE SOURCE OF TRUTH — this script syncs its -# values into package.json and into src/ before building. -# -# Run from the project root: ./build.sh set -euo pipefail cd "$(dirname "$0")" - -echo ">> Reading identity from app.config.js..." -NAME="$(node -p "require('./app.config.js').name")" -WMCLASS="$(node -p "require('./app.config.js').wmClass")" -APPID="$(node -p "require('./app.config.js').appId")" -# slug: lowercase, spaces -> dashes (e.g. "Proton Calendar" -> "proton-calendar") -SLUG="$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')" - -echo " name=$NAME slug=$SLUG appId=$APPID" - -echo ">> Syncing identity into package.json..." -node - "$NAME" "$SLUG" "$APPID" "$WMCLASS" <<'NODE' -const fs = require("fs"); -const [name, slug, appId, wmClass] = process.argv.slice(2); -const pkg = JSON.parse(fs.readFileSync("package.json", "utf8")); -pkg.name = slug; -pkg.productName = name; -pkg.description = name + " desktop wrapper (Electron) by Adam And His Agents"; -pkg.build.appId = appId; -pkg.build.productName = name; -pkg.build.linux.executableName = slug; -// AppImage filename: lowercase slug + -aaha- + version + arch, no spaces. -pkg.build.linux.artifactName = slug + "-aaha-${version}-${arch}.AppImage"; -pkg.build.linux.desktop.Name = name; -pkg.build.linux.desktop.Comment = name + " desktop wrapper"; -pkg.build.linux.desktop.StartupWMClass = wmClass; -fs.writeFileSync("package.json", JSON.stringify(pkg, null, 2) + "\n"); -NODE - -echo ">> Bundling config + icon into src/ (so they pack into app.asar)..." -cp -f app.config.js src/app.config.js -if [ -f icons/icon.png ]; then - cp -f icons/icon.png src/icon.png -else - echo " WARNING: icons/icon.png not found. The app will build but use a" - echo " generic icon. Add a 512x512 PNG at icons/icon.png and rebuild." -fi - -echo ">> Installing dependencies (first run downloads Electron, ~150MB)..." -npm install - -echo ">> Building Linux targets (dir + AppImage)..." +npm ci +npm run check +npm test +npm run icons npm run dist - -echo -echo ">> Done. Outputs are in ./dist/" -echo " - Unpacked app: ./dist/linux-unpacked/" -echo " - AppImage: ./dist/*.AppImage" -echo -echo "Next: run ./install.sh to register the app with your desktop." +appimage="$(find dist -maxdepth 1 -type f -name '*.AppImage' -print -quit)" +if [[ -z "$appimage" ]]; then + echo "ERROR: electron-builder did not produce an AppImage." >&2 + exit 1 +fi +( + cd dist + sha256sum "$(basename "$appimage")" > SHA256SUMS + sha256sum -c SHA256SUMS +) +echo "Build complete: $appimage" diff --git a/build/icons/128x128.png b/build/icons/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..3ba3fa4fb8dbbf1cd9a91a418eb5325e7fd9f84a GIT binary patch literal 6468 zcmZ8`1yIya-2V5D0}k%TaWv8*p>%h5NOve89m3I#2OOYucY~w?(j}azqyh>e%^{7z zAt5FB;=D8eng6>pyU)z-JoDMl)@PsH7y7#DB*b*Y0059^YN#0ABI;j;65N*Wa zqW{YoY%cT$09rOp6-DEq`Te5cLI#tzq5kSRPUQjJSt_9^3Iq*A2rs^`nq}-E^pfmQ zwYY{Sc(@OOK-!TRBND;od*Dl?qTKl(NNzC;zn;N~qEyuVOY{i@K`CfJu92J9Acac_ zt*ee~$ZzYZ%lIQ#5@uWFrL)p~X4Y{ac~-bWwu}0$M20^Roe>!q8K+8xa%}0@{gqXr z)TgiVrI2L-ud6NvVxBMzLuGe6znoD=h1rl9gGeVy0qJ_qj*DoJ9%J`eWkilyV?hv= zk}WBgz_vsmf{+SHNTPku<^c<1KKH^_|Mn6*^tW}JFB+qXFGUfTUg3QQ^_0g~3+=3! ziG$Gx^2B>Yi+oM}@jZ=UcTLD!fu{=6lXicd053y?&KvtLoi+EN%wSLa07jZWXxSk0zxdQktyGf5 zVCQcc{C$l+tcN7FS88G5_lQtS)8b)8K4306G9o_R(^YK}XieJsxdyfxC=@=nb;gEZGrUCd z>Ec>%efaZ5j8?h~;l{lm{xdsfa^?zJ7Rv&1T37)yWC!#&E1;lpbESLn;?F}S`&^b- z6xDHtGBPsG=eHvcXUGlcAEpHXaIh!d??dob_83ie)lxN4Sw#~i+GXxpqs~pw)PWgV z1lmO1NodY^e9Nqmz z$^4#Ow0~2%3q=UYaSUs@(ob7B=>-%iEFfHUv4Rr*bhe^@J7^#R{673bS8*Fy43E*uU=W69>!TSrd3r`;ORS-f%58K44O*^1!dLI?YtY2#Vcr zYw9A|ynxb!g76B``o-zt6=8NnQZjJ`U>gXZ22>z;IE!UY-`NfiL~I}?0*04XA2To0qePy#qY%v^As%QS^hOT!^`aM0TdT$ z

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 V-7kFzRsjY9gQu&X%Q~loCIBOSvIGDC literal 0 HcmV?d00001 diff --git a/build/icons/24x24.png b/build/icons/24x24.png new file mode 100644 index 0000000000000000000000000000000000000000..25fa6645e8459720e2c13ac0d34c95e4895dc2c1 GIT binary patch literal 1438 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaADI|LY`7$t6sWC7#v@kII0tz*} zU|=XUU|@Kaz`$TNgMmT3V9u^U8wLi(e*r!ru0REfJI*TYIIFPzwBpWl$~(^TZ`dhz z^rqtWv&uWpC~ZHhwEdj&&a*1J&dP7SsI=pp;`Vb&+s`QPJfpbnJVYZKY4%f z!1Y&~w>10trriAVFDdcxG>KIkHZB&PuD(L7ecKG1P%*XlZU2%WWb@3m)KUOz!{ zhv*5lFP|Ic8+x9LVkrr^7}tNxgE8NxE$dg_(|bUNGA4PuyD)UH%6b4f>?NMQuI#Va zx!IK@Z|pGyrgjF^64!{5l*E!$tK_0oAjM#0U}UCiV6JOu7-C>9nO2FW!O+ag)DWV(TvzmPxCje+6(97{-4L_M=hPW5 z&uEp)I=6D~hyOqG?4EW>UFGvV^DT|j&na^_om}T7yMggizsq27&A?6X%G zZj5ZcnY327;q1QUd<7Pbdw<8gQ>xhW)owr6Z+@8^i;$KBiBe7O9G0BsZnI`x<#c#_ z(RuUx4DT(b*RHwTiRI={>GM3k_ifPePQU8#^xExLCcm+*e6>a6!u9;E{9mHhzBA6w zP7hugQuX1^&xICDho?=vD7e4=%b^=bz1MAf@}naD)2AaFcqE_fDk}YSE1>Gtu1hH* zGt#*4Y`C*Wbe3Us+UgrxS({!nY=8djeZb=<@Ah{7{va>5t4PS`gTjU%0$dwJj8y^} z-=*GPtR%5nd&LIcD!KM+ip_63H+3tove~(3SEx$Hrb^Y|G{T^aO(Q2%=fzt{_o|}x^m{{!&Bl9p0B@u lz;D|B05+XJYc<4M>QlWk^q-mbHUJX=gQu&X%Q~loCII{>l-vLS literal 0 HcmV?d00001 diff --git a/build/icons/256x256.png b/build/icons/256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..8638dc9034f5e395e0dbbe987bc109b9629df353 GIT binary patch literal 14387 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 literal 0 HcmV?d00001 diff --git a/build/icons/32x32.png b/build/icons/32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..d20bc3dc991d713bd43dfe3f1f115c35afe79986 GIT binary patch literal 1761 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7e6l0AZa85pY67#JE_7#My5g&JNk zFq9fFFuY1&V6d9Oz#v{QXIG#N0|S$PfKP}kP=V5pvx+;;C~Z5VwEe8o&T|a^|10b| zue{@|GLXAtNFtDThNjC=oW1=V3Ky@B6!FRuZw@6YfoX~J_Z2xHb+{zRFBnKefnh%D zv_7WL0E_3<>}-2BF^4@(GynXjn|s%W)b}ax4u6;>$WnatQ)KqX72+ICUng6=3{HHz zRi1ZZyT+@KL(IbSE4AG2pWV4mc5RkPpxMQn4^HiV7NM4$kozMiZ|<*u+uFX&4D#Z7 z^yKm1Z};Rn6&0rZHZnFSJGrH_Twto?qON6(e3O387HasuT1rRd(p^`^c%`fUXQXwL zUTgQ*w>+%9#UoPBA6~S7N5v{ly<__vt~+n^zF@k2f!NA7N^P8*fPP?1@^*J&=wOxg z0CLz%Jbhi+U$JwuD@oqiV+hPy45}rr5hW>!C8<`)MX5lF!N|bKOxM6%*U&J;z}(8% zz{11lnU$#_M1%2`pAkR}8gLs*GILXlOA>Pn(DWFa zSQ(i@^c>qXrx2LG=Xkm}hFF|Vz5F}gJ5h%H!*gekXx-Usw`FZ!Yx=ruMwaI08%|T4 z+OF-LYPMZ>muLBR0U@s-y_2dcPDLkw9^W&sc-7kvf1lc{e_px&-1q8z=f4X$aX8NK z;8~-<^5_Ex=LNd_T9%G+ZGyqx{@hy;bn(k;WA428 z@Hzj*!(ILNy2bn_t$uOo=_~E1C|O5;1_qDatKNxqFaC0U-S@jYD!W(PGYE7&t4eNS z`J}N|=;hz-@9!+tY+_&wO5GC9#Wg`EX!kqL#*z>Jn01(KWHyy;V{d-w-dq?H#&@C1 zt)}0-*+C}wql^dNIEu_Vw4Qy=(WD#3pjq zUw&W5T_<;|Czv5>5%2qZ^)u4!`hpDX4xeW>H}Q*lvi$tgV6M4#l_w0dmnSG>Jkj{^ zsq~ZdkzJOY`^3+9|7Sh6QZPPULiV?%s={3T6XH$s*Yw=~8cbt&vw5lgW|oG;`oC@r z2_=nxl|3e2opShoYj)rM?tA-YBwVyEO7i_-jh}OXDPV%PFfeU1 Nc)I$ztaD0e0sx^5F24W( literal 0 HcmV?d00001 diff --git a/build/icons/48x48.png b/build/icons/48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..16d2c8262c7d35f2e1fae057eecd3dd21a01f6a8 GIT binary patch literal 2386 zcmdT^c~H~W7QTcfB*ZEdBy3p$SwylBffUM8LfDZ-3k52R6oP;V0ToaKhzL9=+j}hv z4^XQhpcTPi0$8G;Y)Q}u0V*Qa3J4-wEeZzck9MXr?SJo0r!())x#v6g&iTG`@64H# zyU&Zg4Xup^0Bm!0aq@+cvbB}vVITSg)dB+{!o}AUfK)>OcxM1ugRgim0Z4`uXF~yC zehq+TLPe{O4FK|BpNBsSP9X8c_%?|_vxo$VNCGjD4+mm0A2tbzFCsz`l0ZU&2J{6Y z0$&1J-;ntt{g!^RKtkS1mgwE;A@apUNQ7_c!!`HfA<@qIL0t0yX^Y-(*xrwC6O#q~ zL`Y2B(vc7Z5&|S92tn6aHGk|5*)g{?zu#8W=XXzFvMX{&&kJ3PJj&O6Q|!_RDw$`cJdFn9^eB zwYMjcw52CszRSn>zmRQ|tICDVO}x2^J+geg`TIqJ@~Mj&{|cTF8vo<{df9gGA4C>v z=g*=YM~CgSYJWbav{&LzY+2yQ@9v!5Pd2(61ikuapO^Nv5r?k}Kg_MXP;q0Wmz(kd z{>QBB%*%BR9fs|<6a^dc5CvZ+t&jmgp zxvrip9odnk+>$&5&hgaObfw7q5&OEW6fpJK_RQg3?>(p@loB0xPEi(Fhy@fi!tQ4HZu?7DohEz@+W;oDb^^Lxy&1^gWkTIbzV z0*i7T-KNk}2l7}o`X+TZRn@hfu)fYn=g8ax-1709%7sDthy<7AJ<%~`Nw2bgx~kVn z2`?%-t|IJdq(*cb7@LL4&O{VO-a|CThtm=&hTO_8S79b)L&gvekGj%ymctRE!cE6( zOXWag?iIE?{iasAy@vwuYL8Q@L*z?i`Vn4edEx7o*l;PhKtE|XUaS(Wot# zCrw|9LU<@xxt~)$(@3rF-Na6trdG6j^ClQ;bCiU_q5xbM>cY{(!zJA@!+ztf{G?UA z>B>!gTScm@bI5Mp}`m)@>!@tZjV)Up=;nFH^oOLQ=h4ACmZ<-@7qJ; z-t{S&$kL3F#M*klosXWWRYz&E8&~=Mi0HIR*-E^RQwFyBSbcfQ+okLh@bq{oKg3oT z`G|lsdivwiobeRiK_MN5I8rPSX!32;z{@c+Tz=#sVg3fxOA0nXzku?Nb!7Sg^VyLg zPS8P%<5#m~E5|1DdUyi09#JT#GtDQIH@RZM*p8SoA-q0m`IXu>B~L-$r~5$?V@HDa zC5P^6P66#;4mj&zuZi-_NG1ZK$u{S7Wf$ZFQ=!Zu?sd*Q0Z>|&F1dA)mHCAY4JVbf zxW$haEK4vTJ=pP0??$LO`d!17ni_fijE$^QcRpVzlH+-M%FgM0W`t5mKXkNhd@ia= zr8;VKGEs4^0a)0-)nq=VMZYU)ucQhY_sILx8P(F5vD9zA>}99V9L_M%v5r}9eGD~a zH+}e({0Pc?y?`cmF*hvJ5Y`+Cgd1q!*|3n zt3R;6>o3H_EJyqLowrHb9E!cda%IcU*p&`$S;+N~;vEfMuvCTidatc6qA{`L^_ddG=o8;77AYH8KJP6>X-&-w=lF$bq05XV4cK`qY literal 0 HcmV?d00001 diff --git a/build/icons/512x512.png b/build/icons/512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..185a4966c75741abc86e82fa515223c142afa993 GIT binary patch literal 9374 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 G_5T3a;kJzc literal 0 HcmV?d00001 diff --git a/build/icons/64x64.png b/build/icons/64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..9f8e0fe8a267e8f68c9bb9017bd9c60614c78462 GIT binary patch literal 3011 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 literal 0 HcmV?d00001 diff --git a/install.sh b/install.sh index bda693d..d1d1a0f 100755 --- a/install.sh +++ b/install.sh @@ -1,60 +1,123 @@ #!/usr/bin/env bash -# Installs the built app into your user environment so KDE/GNOME show it as a -# real, pinnable app with the correct icon on Wayland. -# Run AFTER ./build.sh, from the project root: ./install.sh set -euo pipefail cd "$(dirname "$0")" - -APP_NAME="$(node -p "require('./app.config.js').name")" -WM_CLASS="$(node -p "require('./app.config.js').wmClass")" -SLUG="$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')" - -BIN_DIR="$PWD/dist/linux-unpacked" -BIN_PATH="$BIN_DIR/$SLUG" -if [[ ! -x "$BIN_PATH" ]]; then - BIN_PATH="$(find "$BIN_DIR" -maxdepth 1 -type f -executable | head -n1 || true)" -fi -if [[ -z "${BIN_PATH:-}" || ! -x "$BIN_PATH" ]]; then - echo "ERROR: Could not find the built executable in $BIN_DIR" - echo "Did you run ./build.sh first?" +HOME_DIR="${AAHA_HOME:-$HOME}" +SKIP_SANDBOX="${AAHA_SKIP_SANDBOX_SETUP:-0}" +read_cfg() { node -p "require('./app.config.js').$1"; } +APP_NAME="$(read_cfg productName)" +REPO_NAME="$(read_cfg repoName)" +APP_ID="$(read_cfg appId)" +EXECUTABLE="$(read_cfg executable)" +ICON_NAME="$(read_cfg iconName)" +PROFILE_NAME="$(read_cfg profileName)" +COMMENT="$(read_cfg comment)" +CATEGORY="$(read_cfg category)" +KEYWORDS="$(read_cfg keywords)" +VERSION="$(node -p "require('./package.json').version")" +INSTALL_ROOT="$HOME_DIR/MyApps/$REPO_NAME" +APP_DEST="$INSTALL_ROOT/app" +STAGE_DEST="$INSTALL_ROOT/.app-new-$$" +BUILT_APP="$PWD/dist/linux-unpacked" +if [[ ! -x "$BUILT_APP/$EXECUTABLE" ]]; then + echo "ERROR: Built executable not found. Run ./build.sh first." >&2 exit 1 fi -echo ">> Using binary: $BIN_PATH" - -ICON_DEST="$HOME/.local/share/icons/hicolor/512x512/apps" -mkdir -p "$ICON_DEST" -if [ -f icons/icon.png ]; then - cp "icons/icon.png" "$ICON_DEST/$SLUG.png" - echo ">> Icon installed: $ICON_DEST/$SLUG.png" - ICON_LINE="Icon=$SLUG" +if [[ -f dist/SHA256SUMS ]]; then + (cd dist && sha256sum -c SHA256SUMS) else - echo ">> No icons/icon.png; using a generic icon name." - ICON_LINE="Icon=application-x-executable" + echo "ERROR: dist/SHA256SUMS is missing." >&2 + exit 1 +fi +mkdir -p "$INSTALL_ROOT" +rm -rf "$STAGE_DEST" +cp -a "$BUILT_APP" "$STAGE_DEST" +PRESERVED_SANDBOX=0 +STAGED_SANDBOX="$STAGE_DEST/chrome-sandbox" +INSTALLED_SANDBOX="$APP_DEST/chrome-sandbox" +restore_preserved_sandbox() { + if [[ "$PRESERVED_SANDBOX" == "1" && -f "$STAGED_SANDBOX" && -d "$APP_DEST" ]]; then + mv "$STAGED_SANDBOX" "$INSTALLED_SANDBOX" 2>/dev/null || true + fi +} +trap restore_preserved_sandbox EXIT +if [[ -f "$INSTALLED_SANDBOX" && -f "$STAGED_SANDBOX" ]] && + [[ "$(stat -c '%u:%g:%a' "$INSTALLED_SANDBOX")" == "0:0:4755" ]] && + cmp -s "$INSTALLED_SANDBOX" "$STAGED_SANDBOX"; then + rm -f "$STAGED_SANDBOX" + mv "$INSTALLED_SANDBOX" "$STAGED_SANDBOX" + PRESERVED_SANDBOX=1 fi - -APPS_DIR="$HOME/.local/share/applications" -mkdir -p "$APPS_DIR" -DESKTOP_FILE="$APPS_DIR/$SLUG.desktop" - -cat > "$DESKTOP_FILE" < "$desktop_file" < "$apps_dir/$old_id.desktop" <> Desktop entry written: $DESKTOP_FILE" - -update-desktop-database "$APPS_DIR" 2>/dev/null || true -gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" 2>/dev/null || true -kbuildsycoca6 2>/dev/null || kbuildsycoca5 2>/dev/null || true - -echo -echo ">> Installed '$APP_NAME'. Search for it in your app launcher, open it," -echo " then pin it to your panel/taskbar. The icon should stick." +done < <(node -e "for (const p of require('./app.config.js').compatibilityDesktopIds) console.log(p)") +find "$INSTALL_ROOT" -maxdepth 1 -type f -name '*.AppImage' -delete +cp dist/*.AppImage "$INSTALL_ROOT/" +cp dist/SHA256SUMS "$INSTALL_ROOT/" +if [[ "${AAHA_SKIP_DESKTOP_REFRESH:-0}" != "1" ]]; then + update-desktop-database "$apps_dir" 2>/dev/null || true + gtk-update-icon-cache "$HOME_DIR/.local/share/icons/hicolor" 2>/dev/null || true + kbuildsycoca6 2>/dev/null || kbuildsycoca5 2>/dev/null || true +fi +echo "Installed $APP_NAME v$VERSION under $INSTALL_ROOT" diff --git a/new-app.sh b/new-app.sh deleted file mode 100755 index 323c8ca..0000000 --- a/new-app.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -# Clone this generic scaffold into a fresh app project. -# -# Usage: -# ./new-app.sh "Perplexity" https://www.perplexity.ai -# ./new-app.sh "Proton Calendar" https://calendar.proton.me "https://.../icon-512.png" -# -# Args: -# $1 App name (quoted) e.g. "Proton Calendar" -# $2 URL to wrap e.g. https://calendar.proton.me -# $3 (optional) icon URL a 512x512 PNG to auto-download -set -euo pipefail -cd "$(dirname "$0")" - -NAME="${1:-}" -URL="${2:-}" -ICON_URL="${3:-}" -if [[ -z "$NAME" || -z "$URL" ]]; then - echo "Usage: ./new-app.sh \"App Name\" https://app.url [https://icon-512.png]" - exit 1 -fi - -SLUG="$(echo "$NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')" -DEST="../$SLUG" -APPID="com.adamandhisagents.$(echo "$SLUG" | tr -d '-')" - -if [[ -e "$DEST" ]]; then - echo "ERROR: $DEST already exists. Pick a different name or remove it." - exit 1 -fi - -echo ">> Creating $DEST from the generic scaffold..." -mkdir -p "$DEST" -cp -r src build.sh install.sh uninstall.sh new-app.sh package.json app.config.js "$DEST/" -mkdir -p "$DEST/icons" - -# Write a fresh app.config.js for the new app. -cat > "$DEST/app.config.js" <> Downloading icon from $ICON_URL ..." - if curl -fsSL "$ICON_URL" -o "$DEST/icons/icon.png"; then - echo " Icon saved to $DEST/icons/icon.png" - else - echo " WARNING: icon download failed. Add a 512x512 PNG manually at $DEST/icons/icon.png" - fi -else - echo ">> No icon URL given. Add a 512x512 PNG at $DEST/icons/icon.png before building." -fi - -echo -echo ">> Done. Next steps:" -echo " cd $DEST" -echo " # (ensure icons/icon.png exists — 512x512 PNG)" -echo " ./build.sh && ./install.sh" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..fe86ca5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3595 @@ +{ + "name": "perplexity-aaha", + "version": "1.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "perplexity-aaha", + "version": "1.1.0", + "license": "Apache-2.0", + "devDependencies": { + "electron": "43.1.0", + "electron-builder": "26.15.3" + } + }, + "node_modules/@electron-internal/extract-zip": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@electron-internal/extract-zip/-/extract-zip-1.0.4.tgz", + "integrity": "sha512-Zr1Vs7E9tpCNhZHDAbFVXc2gEVCG9RqPDjrno5+bdgB6LRAuvgyMHJut4NCVyYwtAieapMzc3fiQ3CSTi75ARg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@electron/asar": { + "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": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/fuses": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@electron/fuses/-/fuses-1.8.0.tgz", + "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.1", + "fs-extra": "^9.0.1", + "minimist": "^1.2.5" + }, + "bin": { + "electron-fuses": "dist/bin.js" + } + }, + "node_modules/@electron/fuses/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/get": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-5.0.0.tgz", + "integrity": "sha512-pjoBpru1KdEtcExBnuHAP1cAc/5faoedw0hzJkL3o4/IJp7HNF1+fbrdxT3gMYRX2oJfvnA/WXeCTVQpYYxyJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^3.0.0", + "graceful-fs": "^4.2.11", + "progress": "^2.0.3", + "semver": "^7.6.3", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=22.12.0" + }, + "optionalDependencies": { + "undici": "^7.24.4" + } + }, + "node_modules/@electron/notarize": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.3.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": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/rebuild": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.2.0.tgz", + "integrity": "sha512-RKL/O+jGoXJMxrx/5771y1n0xTKmFuOYGO3gMmwypBM6rsH0kou0mswwdXA2JrhIkE4xyC7v9vGk0n6NPzgOxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.1.1", + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^12.2.0", + "read-binary-file-arch": "^1.0.6" + }, + "bin": { + "electron-rebuild": "lib/cli.js" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/@electron/universal": { + "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.3.1", + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.3.1", + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" + }, + "engines": { + "node": ">=16.4" + } + }, + "node_modules/@electron/universal/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@electron/windows-sign": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", + "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "peer": true, + "dependencies": { + "cross-dirname": "^0.1.0", + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "minimist": "^1.2.8", + "postject": "^1.0.0-alpha.6" + }, + "bin": { + "electron-windows-sign": "bin/electron-windows-sign.js" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/windows-sign/node_modules/fs-extra": { + "version": "11.3.6", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "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", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@noble/hashes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.7.1.tgz", + "integrity": "sha512-ODOov0sGMJMf3jPonOkgGqPknTsu+DdQ7kD++gz8aI+aFMOMHFbWAA2taqXXVTdP+OTOQR/znGvSpmkeI0WTYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/utils": "^2.0.2", + "tslib": "^2.8.1", + "webcrypto-core": "^1.9.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-lib": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.15.3.tgz", + "integrity": "sha512-2VnyWkqsP5v5XbBhL3tD5Syx8iNPBYsoU7kY4S2fz7wg8Rj/nztWKCUzGKaFRTv0Xwf3/H058CR1Kvtd/3lRow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "3.4.1", + "@electron/fuses": "^1.8.0", + "@electron/get": "^3.0.0", + "@electron/notarize": "2.5.0", + "@electron/osx-sign": "1.3.3", + "@electron/rebuild": "^4.0.4", + "@electron/universal": "2.0.3", + "@malept/flatpak-bundler": "^0.4.0", + "@noble/hashes": "^2.2.0", + "@peculiar/webcrypto": "^1.7.1", + "@types/fs-extra": "9.0.13", + "ajv": "^8.18.0", + "asn1js": "^3.0.10", + "async-exit-hook": "^2.0.1", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", + "chromium-pickle-js": "^0.2.0", + "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.15.3", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.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.2.5", + "pkijs": "^3.4.0", + "plist": "3.1.0", + "proper-lockfile": "^4.1.2", + "resedit": "^1.7.0", + "semver": "~7.7.3", + "tar": "^7.5.7", + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0", + "unzipper": "^0.12.3", + "which": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "26.15.3", + "electron-builder-squirrel-windows": "26.15.3" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-3.1.0.tgz", + "integrity": "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=14" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/app-builder-lib/node_modules/ci-info": { + "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": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/app-builder-lib/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.15.3.tgz", + "integrity": "sha512-q2hn7Mbo2nFNkVekPiHFx6Nfo3hURmES3tfBn+k5Pqxl2RkmP3QGqZUhH/q9Pch/4G05NRhPjDlVj1O8q4Txvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "builder-util-runtime": "9.7.0", + "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", + "js-yaml": "^4.1.0", + "sanitize-filename": "^1.6.3", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz", + "integrity": "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/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/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-dirname": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", + "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/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", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5", + "p-limit": "^3.1.0 " + } + }, + "node_modules/dir-compare/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.15.3.tgz", + "integrity": "sha512-O3zJUFUYHJKgzPqioHxfxzBzlSC1eXCSr79gMSBKBP5AgjjpmrydMsMLotEg9fAJF36vdUncb+4ndRNxoPdlSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "43.1.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-43.1.0.tgz", + "integrity": "sha512-DPfxpQLd4NL3BJ8DBxYAfmLUKKesF5Rx9dQx5FyczAP8bhOPScjHE48GArVeXu68LlAainuwkmQTQvdZwpIIAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron-internal/extract-zip": "^1.0.1", + "@electron/get": "^5.0.0", + "@types/node": "^24.9.0" + }, + "bin": { + "electron": "cli.js", + "install-electron": "install.js" + }, + "engines": { + "node": ">= 22.12.0" + } + }, + "node_modules/electron-builder": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.15.3.tgz", + "integrity": "sha512-a1KM5heqS3gQCZzizXEI8RjJy3QVogULPdeSknt76uLDpBIW/HDGsMg/XgP0riP6PI9COsRvFITKKGDqA8fJxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "dmg-builder": "26.15.3", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.15.3.tgz", + "integrity": "sha512-Jc19XPV9y9+2bAdZPkXuVNGNIEFBq9poHC61l8Kv6FdK7DRG3+Ic0rerC0DXOaeHNz8yW0fg/JnF8GQROOF5MA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "electron-winstaller": "5.4.0" + } + }, + "node_modules/electron-publish": { + "version": "26.15.3", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.15.3.tgz", + "integrity": "sha512-g/2bn8YTavY4cuS5F+jOS7zmZbXXBV8KZ8yHKfJjFPoKtzBqrpCdNPxBd3tqdBwP7BVd0lGzf7Bk2s0KesWZ4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "aws4": "^1.13.2", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", + "chalk": "^4.1.2", + "form-data": "^4.0.5", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-winstaller": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", + "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.21", + "temp": "^0.9.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "@electron/windows-sign": "^1.1.2" + } + }, + "node_modules/electron-winstaller/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/electron-winstaller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-winstaller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "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/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-yaml": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "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": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "4.33.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.33.0.tgz", + "integrity": "sha512-vLBWCKb+7LWsX+TbfzWOkw0W81m377tyx3hOweBTjO43CXZnRGS1/JPWs20fr0PgZyDXk6ROYrylsEycK8raDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + }, + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/node-api-version": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", + "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + } + }, + "node_modules/node-gyp": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/node-gyp/node_modules/undici": { + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", + "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pe-library": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", + "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/pkijs/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/postject/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-binary-file-arch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", + "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "bin": { + "read-binary-file-arch": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resedit": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", + "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pe-library": "^0.4.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "7.5.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz", + "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==", + "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/tar/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/temp": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "mkdirp": "^0.5.1", + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/tiny-async-pool": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", + "integrity": "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.5.0" + } + }, + "node_modules/tiny-async-pool/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "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/unzipper": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.12.5.tgz", + "integrity": "sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "~3.7.2", + "duplexer2": "~0.1.4", + "fs-extra": "11.3.1", + "graceful-fs": "^4.2.2", + "node-int64": "^0.4.0" + } + }, + "node_modules/unzipper/node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/webcrypto-core": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.9.2.tgz", + "integrity": "sha512-gsXecm82UQNlTBURJGuqOWy1Ww08S3kZUcr3aOJS02Pk0xLtkfeUAVC0u0xhgdonFme80edSJUIJyuvL/7250Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/which": { + "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": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index e08cf61..20478ae 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,38 @@ { - "name": "perplexity", + "name": "perplexity-aaha", "productName": "Perplexity", - "version": "1.0.0", - "description": "Perplexity desktop app (Electron wrapper) by Adam And His Agents", + "desktopName": "com.adamandhisagents.perplexity", + "version": "1.1.0", + "description": "Unofficial Perplexity desktop application for Linux by Adam And His Agents", "main": "src/main.js", "author": "Adam And His Agents (AAHA)", "license": "Apache-2.0", "scripts": { "start": "electron .", + "check": "node --check src/main.js && node --check src/policy.js && node --check app.config.js && node scripts/validate-config.js", + "test": "node --test", + "icons": "bash scripts/generate-icons.sh", "dist": "electron-builder --linux" }, - "devDependencies": { - "electron": "^31.0.0", - "electron-builder": "^24.13.3" - }, + "devDependencies": { "electron": "43.1.0", "electron-builder": "26.15.3" }, "build": { "appId": "com.adamandhisagents.perplexity", "productName": "Perplexity", "asar": true, - "files": [ - "src/**/*", - "package.json" - ], + "files": ["src/**/*", "app.config.js", "build/icons/**/*", "package.json"], "linux": { - "target": [ - "dir", - "AppImage" - ], + "target": ["dir", "AppImage"], "category": "Network", - "icon": "icons", - "executableName": "perplexity", - "artifactName": "perplexity-aaha-${version}-${arch}.AppImage", - "desktop": { - "Name": "Perplexity", - "Comment": "AI-powered answer engine", - "Categories": "Network;", - "StartupWMClass": "Perplexity" - } + "icon": "build/icons", + "executableName": "perplexity-aaha", + "artifactName": "perplexity-aaha-v${version}-${arch}.AppImage", + "syncDesktopName": true, + "desktop": { "entry": { + "Name": "Perplexity", "Comment": "Perplexity AI answer engine", + "Categories": "Network;", "Keywords": "ai;search;research;perplexity;", + "StartupWMClass": "com.adamandhisagents.perplexity", + "Terminal": false, "Type": "Application" + }} } } } diff --git a/scripts/generate-icons.sh b/scripts/generate-icons.sh new file mode 100755 index 0000000..43c6c93 --- /dev/null +++ b/scripts/generate-icons.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail +cd "$(dirname "$0")/.." +SOURCE="assets/icon-source.png" +if [[ ! -f "$SOURCE" ]]; then + echo "ERROR: $SOURCE is required." >&2 + exit 1 +fi +mkdir -p build/icons +for size in 16 24 32 48 64 96 128 256 512; do + magick "$SOURCE" -background none -resize "${size}x${size}" "build/icons/${size}x${size}.png" +done +identify_output="$(magick identify -format '%m %w %h %[channels]' build/icons/512x512.png)" +if [[ "$identify_output" != PNG*512*512* ]]; then + echo "ERROR: generated icon validation failed: $identify_output" >&2 + exit 1 +fi +echo "Generated icon set from $SOURCE" diff --git a/scripts/validate-config.js b/scripts/validate-config.js new file mode 100644 index 0000000..24ed807 --- /dev/null +++ b/scripts/validate-config.js @@ -0,0 +1,12 @@ +"use strict"; + +const cfg = require("../app.config.js"); +const { validateConfig } = require("../src/policy.js"); + +const template = process.argv.includes("--template"); +const errors = validateConfig(cfg, { template }); +if (errors.length) { + console.error(errors.map((error) => `- ${error}`).join("\n")); + process.exit(1); +} +console.log(template ? "Template structure is valid." : "Application configuration is valid."); diff --git a/src/main.js b/src/main.js index 26e21b5..245f908 100644 --- a/src/main.js +++ b/src/main.js @@ -1,103 +1,135 @@ -const { app, BrowserWindow, shell, Menu } = require("electron"); -const path = require("path"); -const cfg = require("./app.config.js"); +"use strict"; -// Set the Wayland/X11 app id BEFORE the app is ready so KDE associates -// the window with the correct .desktop entry and keeps your custom icon. -app.setName(cfg.name); -if (process.platform === "linux") { - // This is what KDE Plasma reads as the WM class on Wayland. - app.commandLine.appendSwitch("class", cfg.wmClass); +const { app, BrowserWindow, Menu, session, shell } = require("electron"); +const path = require("node:path"); +const cfg = require("../app.config.js"); +const { + classifyNavigation, + isBlockedRequest, + parseUrl, + permissionAllowed, + validateConfig +} = require("./policy.js"); + +const errors = validateConfig(cfg); +if (errors.length) { + throw new Error(`Invalid app.config.js:\n- ${errors.join("\n- ")}`); } -// --------------------------------------------------------------------------- -// PRIVACY HARDENING -// Electron's embedded Chromium already omits most browser-level Google -// services (Safe Browsing, sync, GoogleURLTracker, the Chrome updater, etc.) -// because it is an app runtime, not a browser. These switches make that -// explicit and shut off the remaining background/phone-home subsystems so -// the app stays network-silent except for the site it wraps. -// Set cfg.disableHardening = true in app.config.js to opt out. -// --------------------------------------------------------------------------- -if (!cfg.disableHardening) { - app.commandLine.appendSwitch("disable-background-networking"); - app.commandLine.appendSwitch("disable-domain-reliability"); - app.commandLine.appendSwitch("disable-component-update"); - app.commandLine.appendSwitch( - "disable-features", - "NetworkTimeServiceQuerying,Translate,OptimizationHints,MediaRouter" - ); - app.commandLine.appendSwitch("disable-breakpad"); +app.setName(cfg.productName); +app.setPath("userData", path.join(app.getPath("appData"), cfg.profileName)); + +if (process.platform === "linux") { + app.commandLine.appendSwitch("class", cfg.appId); } +app.commandLine.appendSwitch("disable-background-networking"); +app.commandLine.appendSwitch("disable-component-update"); +app.commandLine.appendSwitch("disable-domain-reliability"); +app.commandLine.appendSwitch("disable-breakpad"); +app.commandLine.appendSwitch("dns-over-https-mode", "off"); +app.commandLine.appendSwitch( + "disable-features", + "NetworkTimeServiceQuerying,Translate,OptimizationHints,MediaRouter" +); + let mainWindow; +const auditedHosts = new Set(); + +function safeOpenExternal(url) { + if (classifyNavigation(url, cfg) !== "external") return; + setImmediate(() => shell.openExternal(url).catch((error) => console.error("[external]", error.message))); +} + +function secureWebPreferences() { + return { + sandbox: true, + contextIsolation: true, + nodeIntegration: false, + webSecurity: true, + allowRunningInsecureContent: false, + spellcheck: true + }; +} -function hostMatches(urlString) { - if (!cfg.allowedHosts || cfg.allowedHosts.length === 0) return true; - try { - const host = new URL(urlString).hostname; - return cfg.allowedHosts.some( - (h) => host === h || host.endsWith("." + h) - ); - } catch (e) { - return false; +function configureWebContents(contents) { + contents.on("will-attach-webview", (event) => event.preventDefault()); + + for (const eventName of ["will-navigate", "will-redirect"]) { + contents.on(eventName, (event, url) => { + const classification = classifyNavigation(url, cfg); + if (classification === "internal" || classification === "authentication") return; + event.preventDefault(); + safeOpenExternal(url); + }); } + + contents.setWindowOpenHandler(({ url }) => { + const classification = classifyNavigation(url, cfg); + if (classification === "internal" || classification === "authentication") { + return { + action: "allow", + overrideBrowserWindowOptions: { + autoHideMenuBar: true, + parent: mainWindow || undefined, + webPreferences: secureWebPreferences() + }, + outlivesOpener: false + }; + } + safeOpenExternal(url); + return { action: "deny" }; + }); } function createWindow() { mainWindow = new BrowserWindow({ width: cfg.width, height: cfg.height, - title: cfg.name, + title: cfg.productName, autoHideMenuBar: true, - icon: path.join(__dirname, "icon.png"), - webPreferences: { - contextIsolation: true, - nodeIntegration: false, - spellcheck: true - } + icon: path.join(__dirname, "../build/icons/512x512.png"), + webPreferences: secureWebPreferences() }); + mainWindow.loadURL(cfg.url); +} - // Optional custom user-agent (helps sites that sniff for a "real" browser). - const loadOpts = {}; - if (cfg.userAgent) { - loadOpts.userAgent = cfg.userAgent; - } - mainWindow.loadURL(cfg.url, loadOpts); - - // Links that open a NEW window/tab -> send to system browser if external. - mainWindow.webContents.setWindowOpenHandler(({ url }) => { - if (cfg.openExternalInBrowser && !hostMatches(url)) { - shell.openExternal(url); - return { action: "deny" }; - } - return { action: "allow" }; +function configureSession() { + const ses = session.defaultSession; + ses.setPermissionCheckHandler((webContents, permission, requestingOrigin) => { + const origin = requestingOrigin || webContents?.getURL() || ""; + return permissionAllowed(permission, origin, cfg); + }); + ses.setPermissionRequestHandler((webContents, permission, callback, details) => { + const origin = details.requestingUrl || webContents?.getURL() || ""; + callback(permissionAllowed(permission, origin, cfg)); }); - // In-page navigation to a foreign host -> bounce to system browser. - mainWindow.webContents.on("will-navigate", (event, url) => { - if (cfg.openExternalInBrowser && !hostMatches(url)) { - event.preventDefault(); - shell.openExternal(url); + ses.webRequest.onBeforeRequest((details, callback) => { + const parsed = parseUrl(details.url); + if (process.env.AAHA_NETWORK_AUDIT === "1" && parsed && !auditedHosts.has(parsed.hostname)) { + auditedHosts.add(parsed.hostname); + console.error(`[network] ${parsed.hostname}`); } + callback({ cancel: isBlockedRequest(details.url, cfg) }); }); } -// Single-instance lock: clicking the panel icon focuses the existing -// window instead of spawning a second copy. const gotLock = app.requestSingleInstanceLock(); if (!gotLock) { app.quit(); } else { + app.on("web-contents-created", (_event, contents) => configureWebContents(contents)); app.on("second-instance", () => { - if (mainWindow) { - if (mainWindow.isMinimized()) mainWindow.restore(); - mainWindow.focus(); - } + if (!mainWindow) return; + if (mainWindow.isMinimized()) mainWindow.restore(); + mainWindow.show(); + mainWindow.focus(); }); app.whenReady().then(() => { - Menu.setApplicationMenu(null); // clean, app-like (no menu bar) + Menu.setApplicationMenu(null); + configureSession(); createWindow(); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) createWindow(); diff --git a/src/policy.js b/src/policy.js new file mode 100644 index 0000000..4ed78f1 --- /dev/null +++ b/src/policy.js @@ -0,0 +1,134 @@ +"use strict"; + +const REQUIRED_STRINGS = [ + "repoName", + "productName", + "appId", + "executable", + "iconName", + "profileName", + "url" +]; + +function parseUrl(value) { + try { + return new URL(value); + } catch { + return null; + } +} + +function normalizeHost(value) { + return String(value || "").trim().toLowerCase().replace(/^\.+/, ""); +} + +function hostMatches(hostname, rule) { + const host = normalizeHost(hostname); + const wanted = normalizeHost(rule); + return Boolean(host && wanted && (host === wanted || host.endsWith(`.${wanted}`))); +} + +function hostInRules(hostname, rules = []) { + return Array.isArray(rules) && rules.some((rule) => hostMatches(hostname, rule)); +} + +function isHttpsHost(urlString, rules) { + const parsed = parseUrl(urlString); + return Boolean(parsed && parsed.protocol === "https:" && hostInRules(parsed.hostname, rules)); +} + +function isTrustedNavigation(urlString, cfg) { + return isHttpsHost(urlString, cfg.trustedNavigationHosts); +} + +function isTrustedAuthentication(urlString, cfg) { + return isHttpsHost(urlString, cfg.trustedAuthHosts); +} + +function isSafeExternal(urlString, cfg) { + const parsed = parseUrl(urlString); + return Boolean( + parsed && + cfg.openExternalLinks && + Array.isArray(cfg.externalProtocols) && + cfg.externalProtocols.includes(parsed.protocol) + ); +} + +function classifyNavigation(urlString, cfg) { + if (isTrustedNavigation(urlString, cfg)) return "internal"; + if (isTrustedAuthentication(urlString, cfg)) return "authentication"; + if (isSafeExternal(urlString, cfg)) return "external"; + return "deny"; +} + +function permissionAllowed(permission, urlString, cfg) { + const parsed = parseUrl(urlString); + const rules = cfg.permissions && cfg.permissions[permission]; + return Boolean( + parsed && + parsed.protocol === "https:" && + Array.isArray(rules) && + hostInRules(parsed.hostname, rules) + ); +} + +function isBlockedRequest(urlString, cfg) { + const parsed = parseUrl(urlString); + return Boolean(parsed && hostInRules(parsed.hostname, cfg.blockedHosts)); +} + +function validateConfig(cfg, { template = false } = {}) { + const errors = []; + if (!cfg || typeof cfg !== "object") return ["Configuration must export an object."]; + if (cfg.schemaVersion !== 2) errors.push("schemaVersion must be 2."); + if (!template && cfg.configured !== true) errors.push("configured must be true for an application build."); + + for (const key of REQUIRED_STRINGS) { + if (typeof cfg[key] !== "string" || !cfg[key].trim()) errors.push(`${key} must be a non-empty string.`); + } + + const url = parseUrl(cfg.url); + if (!template && (!url || url.protocol !== "https:")) errors.push("url must be a valid HTTPS URL."); + if (!template && (!Array.isArray(cfg.trustedNavigationHosts) || cfg.trustedNavigationHosts.length === 0)) { + errors.push("trustedNavigationHosts must contain at least one host."); + } + + for (const key of [ + "legacyProfileNames", + "compatibilityDesktopIds", + "trustedNavigationHosts", + "trustedAuthHosts", + "blockedHosts", + "externalProtocols" + ]) { + if (!Array.isArray(cfg[key])) errors.push(`${key} must be an array.`); + } + + if (!cfg.permissions || typeof cfg.permissions !== "object" || Array.isArray(cfg.permissions)) { + errors.push("permissions must be an object."); + } else { + for (const [permission, rules] of Object.entries(cfg.permissions)) { + if (!permission || !Array.isArray(rules)) errors.push(`permissions.${permission} must be an array.`); + } + } + + if (!Number.isInteger(cfg.width) || cfg.width < 640) errors.push("width must be an integer of at least 640."); + if (!Number.isInteger(cfg.height) || cfg.height < 480) errors.push("height must be an integer of at least 480."); + if (cfg.openExternalLinks !== true && cfg.openExternalLinks !== false) { + errors.push("openExternalLinks must be boolean."); + } + return errors; +} + +module.exports = { + classifyNavigation, + hostMatches, + isBlockedRequest, + isSafeExternal, + isTrustedAuthentication, + isTrustedNavigation, + parseUrl, + permissionAllowed, + validateConfig +}; diff --git a/test/policy.test.js b/test/policy.test.js new file mode 100644 index 0000000..d362168 --- /dev/null +++ b/test/policy.test.js @@ -0,0 +1,38 @@ +"use strict"; +const test = require("node:test"); +const assert = require("node:assert/strict"); +const { classifyNavigation, hostMatches, isBlockedRequest, permissionAllowed, validateConfig } = require("../src/policy.js"); +const cfg = { + schemaVersion: 2, configured: true, repoName: "example-aaha", productName: "Example", + appId: "com.adamandhisagents.example", executable: "example-aaha", iconName: "example-aaha", + profileName: "Example", legacyProfileNames: [], compatibilityDesktopIds: [], + url: "https://app.example.com", trustedNavigationHosts: ["example.com"], + trustedAuthHosts: ["login.example.net"], permissions: { notifications: ["app.example.com"] }, + blockedHosts: ["tracker.invalid"], externalProtocols: ["https:", "mailto:"], + openExternalLinks: true, width: 1280, height: 800 +}; +test("host matching rejects deceptive suffixes", () => { + assert.equal(hostMatches("sub.example.com", "example.com"), true); + assert.equal(hostMatches("example.com.attacker.invalid", "example.com"), false); +}); +test("navigation separates app, auth, external, and unsafe URLs", () => { + assert.equal(classifyNavigation("https://app.example.com/page", cfg), "internal"); + assert.equal(classifyNavigation("https://login.example.net/start", cfg), "authentication"); + assert.equal(classifyNavigation("https://external.example.org", cfg), "external"); + assert.equal(classifyNavigation("file:///etc/passwd", cfg), "deny"); + assert.equal(classifyNavigation("javascript:alert(1)", cfg), "deny"); +}); +test("permissions default deny and require approved HTTPS hosts", () => { + assert.equal(permissionAllowed("notifications", "https://app.example.com", cfg), true); + assert.equal(permissionAllowed("media", "https://app.example.com", cfg), false); + assert.equal(permissionAllowed("notifications", "http://app.example.com", cfg), false); +}); +test("blocklist matches subdomains without lookalikes", () => { + assert.equal(isBlockedRequest("https://a.tracker.invalid/pixel", cfg), true); + assert.equal(isBlockedRequest("https://tracker.invalid.example.com", cfg), false); +}); +test("application validation rejects incomplete templates", () => { + const incomplete = { ...cfg, configured: false, trustedNavigationHosts: [] }; + assert.ok(validateConfig(incomplete).length >= 2); + assert.equal(validateConfig(incomplete, { template: true }).length, 0); +}); diff --git a/test/uninstall.test.js b/test/uninstall.test.js new file mode 100644 index 0000000..c5682cf --- /dev/null +++ b/test/uninstall.test.js @@ -0,0 +1,44 @@ +"use strict"; +const test = require("node:test"); +const assert = require("node:assert/strict"); +const fs = require("node:fs"); +const os = require("node:os"); +const path = require("node:path"); +const { spawnSync } = require("node:child_process"); +const root = path.resolve(__dirname, ".."); +const profileName = require("../app.config.js").profileName; +function run(home, args = []) { + return spawnSync("bash", ["uninstall.sh", ...args], { + cwd: root, + env: { ...process.env, AAHA_HOME: home, AAHA_SKIP_DESKTOP_REFRESH: "1" }, + encoding: "utf8" + }); +} +test("normal uninstall preserves profile", () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), "aaha-uninstall-")); + const profile = path.join(home, ".config", profileName); + fs.mkdirSync(profile, { recursive: true }); + fs.writeFileSync(path.join(profile, "cookie"), "preserve"); + const result = run(home); + assert.equal(result.status, 0, result.stderr); + assert.equal(fs.existsSync(profile), true); +}); +test("--purge removes only configured profile", () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), "aaha-purge-")); + const profile = path.join(home, ".config", profileName); + const unrelated = path.join(home, ".config", "Unrelated"); + fs.mkdirSync(profile, { recursive: true }); + fs.mkdirSync(unrelated, { recursive: true }); + const result = run(home, ["--purge"]); + assert.equal(result.status, 0, result.stderr); + assert.equal(fs.existsSync(profile), false); + assert.equal(fs.existsSync(unrelated), true); +}); +test("unknown arguments fail without deleting", () => { + const home = fs.mkdtempSync(path.join(os.tmpdir(), "aaha-unknown-")); + const marker = path.join(home, "marker"); + fs.writeFileSync(marker, "safe"); + const result = run(home, ["--destroy-everything"]); + assert.equal(result.status, 2); + assert.equal(fs.existsSync(marker), true); +}); diff --git a/uninstall.sh b/uninstall.sh index 824a3b3..8d6981f 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,11 +1,42 @@ #!/usr/bin/env bash -# Removes the installed .desktop entry and icon for this app. set -euo pipefail cd "$(dirname "$0")" -APP_NAME="$(node -p "require('./app.config.js').name")" -SLUG="$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')" -rm -f "$HOME/.local/share/applications/$SLUG.desktop" -rm -f "$HOME/.local/share/icons/hicolor/512x512/apps/$SLUG.png" -update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true -kbuildsycoca6 2>/dev/null || kbuildsycoca5 2>/dev/null || true -echo ">> Removed '$APP_NAME' launcher and icon." +usage() { + echo "Usage: ./uninstall.sh [--purge]" + echo " no argument Remove app files, launchers, and icons; preserve profile." + echo " --purge Also remove the local Electron profile and sessions." +} +PURGE=0 +case "${1:-}" in + "") ;; + --purge) PURGE=1 ;; + -h|--help) usage; exit 0 ;; + *) usage >&2; exit 2 ;; +esac +if [[ $# -gt 1 ]]; then usage >&2; exit 2; fi +HOME_DIR="${AAHA_HOME:-$HOME}" +read_cfg() { node -p "require('./app.config.js').$1"; } +APP_NAME="$(read_cfg productName)" +REPO_NAME="$(read_cfg repoName)" +APP_ID="$(read_cfg appId)" +ICON_NAME="$(read_cfg iconName)" +PROFILE_NAME="$(read_cfg profileName)" +rm -rf "$HOME_DIR/MyApps/$REPO_NAME" +rm -f "$HOME_DIR/.local/share/applications/$APP_ID.desktop" +while IFS= read -r old_id; do + [[ -n "$old_id" ]] && rm -f "$HOME_DIR/.local/share/applications/$old_id.desktop" +done < <(node -e "for (const p of require('./app.config.js').compatibilityDesktopIds) console.log(p)") +for size in 16 24 32 48 64 96 128 256 512; do + rm -f "$HOME_DIR/.local/share/icons/hicolor/${size}x${size}/apps/$ICON_NAME.png" +done +if [[ "$PURGE" == "1" ]]; then + rm -rf "$HOME_DIR/.config/$PROFILE_NAME" + echo "Purged local profile: $HOME_DIR/.config/$PROFILE_NAME" +else + echo "Preserved local profile: $HOME_DIR/.config/$PROFILE_NAME" +fi +if [[ "${AAHA_SKIP_DESKTOP_REFRESH:-0}" != "1" ]]; then + update-desktop-database "$HOME_DIR/.local/share/applications" 2>/dev/null || true + kbuildsycoca6 2>/dev/null || kbuildsycoca5 2>/dev/null || true +fi +echo "Removed $APP_NAME." From fcf19ce6cb7a81cecc7577dd0815d5d5a3e1b36a Mon Sep 17 00:00:00 2001 From: satori Date: Sat, 11 Jul 2026 00:44:06 -0700 Subject: [PATCH 2/2] Fix ImageMagick compatibility in CI --- .github/workflows/ci.yml | 5 +++-- scripts/generate-icons.sh | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 43bf6c3..d8f8db8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: permissions: contents: read jobs: - validate-template: + validate-app: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -14,9 +14,10 @@ jobs: with: node-version: 22 cache: npm + - run: sudo apt-get update && sudo apt-get install -y imagemagick - run: npm ci - run: npm run check - run: npm test - - run: bash -n build.sh install.sh uninstall.sh new-app.sh scripts/generate-icons.sh + - run: bash -n build.sh install.sh uninstall.sh scripts/generate-icons.sh - run: npm audit --audit-level=high - run: ./build.sh diff --git a/scripts/generate-icons.sh b/scripts/generate-icons.sh index 43c6c93..9474aa8 100755 --- a/scripts/generate-icons.sh +++ b/scripts/generate-icons.sh @@ -7,10 +7,20 @@ if [[ ! -f "$SOURCE" ]]; then exit 1 fi mkdir -p build/icons +if command -v magick >/dev/null 2>&1; then + resize=(magick) + identify=(magick identify) +elif command -v convert >/dev/null 2>&1 && command -v identify >/dev/null 2>&1; then + resize=(convert) + identify=(identify) +else + echo "ERROR: ImageMagick 6 or 7 is required to generate icons." >&2 + exit 1 +fi for size in 16 24 32 48 64 96 128 256 512; do - magick "$SOURCE" -background none -resize "${size}x${size}" "build/icons/${size}x${size}.png" + "${resize[@]}" "$SOURCE" -background none -resize "${size}x${size}" "build/icons/${size}x${size}.png" done -identify_output="$(magick identify -format '%m %w %h %[channels]' build/icons/512x512.png)" +identify_output="$("${identify[@]}" -format '%m %w %h %[channels]' build/icons/512x512.png)" if [[ "$identify_output" != PNG*512*512* ]]; then echo "ERROR: generated icon validation failed: $identify_output" >&2 exit 1