From 8fe8a944187ed9da51e50fa05eb35d7b740389ee Mon Sep 17 00:00:00 2001 From: "K. Kaushik Reddy" Date: Mon, 3 Aug 2026 23:25:16 -0700 Subject: [PATCH 1/2] desktop-client init --- .github/workflows/desktop-release.yml | 93 + AGENTS.md | 21 + CLAUDE.md | 66 + desktop/.gitignore | 4 + desktop/README.md | 210 ++ desktop/build/entitlements.mac.plist | 22 + desktop/build/icon.png | Bin 0 -> 197185 bytes desktop/build/icon.svg | 12 + desktop/package-lock.json | 3712 ++++++++++++++++++++ desktop/package.json | 162 + desktop/scripts/generate-icons.js | 52 + desktop/scripts/smoke.js | 100 + desktop/scripts/tunnel-selftest.js | 270 ++ desktop/src/main/config.js | 50 + desktop/src/main/index.js | 139 + desktop/src/main/ipc.js | 177 + desktop/src/main/logger.js | 61 + desktop/src/main/menu.js | 153 + desktop/src/main/probe.js | 130 + desktop/src/main/profiles.js | 294 ++ desktop/src/main/secrets.js | 89 + desktop/src/main/tls.js | 189 + desktop/src/main/transport.js | 206 ++ desktop/src/main/tunnel.js | 479 +++ desktop/src/main/updater.js | 60 + desktop/src/main/windows/launcher.js | 89 + desktop/src/main/windows/workspace.js | 360 ++ desktop/src/preload/chrome.js | 20 + desktop/src/preload/launcher.js | 43 + desktop/src/renderer/chrome/chrome.css | 227 ++ desktop/src/renderer/chrome/chrome.js | 96 + desktop/src/renderer/chrome/index.html | 97 + desktop/src/renderer/launcher/index.html | 252 ++ desktop/src/renderer/launcher/launcher.css | 532 +++ desktop/src/renderer/launcher/launcher.js | 509 +++ desktop/src/renderer/shared/theme.css | 206 ++ 36 files changed, 9182 insertions(+) create mode 100644 .github/workflows/desktop-release.yml create mode 100644 desktop/.gitignore create mode 100644 desktop/README.md create mode 100644 desktop/build/entitlements.mac.plist create mode 100644 desktop/build/icon.png create mode 100644 desktop/build/icon.svg create mode 100644 desktop/package-lock.json create mode 100644 desktop/package.json create mode 100644 desktop/scripts/generate-icons.js create mode 100644 desktop/scripts/smoke.js create mode 100644 desktop/scripts/tunnel-selftest.js create mode 100644 desktop/src/main/config.js create mode 100644 desktop/src/main/index.js create mode 100644 desktop/src/main/ipc.js create mode 100644 desktop/src/main/logger.js create mode 100644 desktop/src/main/menu.js create mode 100644 desktop/src/main/probe.js create mode 100644 desktop/src/main/profiles.js create mode 100644 desktop/src/main/secrets.js create mode 100644 desktop/src/main/tls.js create mode 100644 desktop/src/main/transport.js create mode 100644 desktop/src/main/tunnel.js create mode 100644 desktop/src/main/updater.js create mode 100644 desktop/src/main/windows/launcher.js create mode 100644 desktop/src/main/windows/workspace.js create mode 100644 desktop/src/preload/chrome.js create mode 100644 desktop/src/preload/launcher.js create mode 100644 desktop/src/renderer/chrome/chrome.css create mode 100644 desktop/src/renderer/chrome/chrome.js create mode 100644 desktop/src/renderer/chrome/index.html create mode 100644 desktop/src/renderer/launcher/index.html create mode 100644 desktop/src/renderer/launcher/launcher.css create mode 100644 desktop/src/renderer/launcher/launcher.js create mode 100644 desktop/src/renderer/shared/theme.css diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml new file mode 100644 index 0000000..42799aa --- /dev/null +++ b/.github/workflows/desktop-release.yml @@ -0,0 +1,93 @@ +name: desktop-release + +# Builds the DeepSQL desktop client for every platform. Each OS builds its own +# targets on its own runner: cross-building Windows needs Wine and Linux targets +# need a matching glibc, and both are far less reliable than just using the +# native runner. +# +# Tag-triggered runs attach the installers to the GitHub release. Manual runs +# upload them as workflow artifacts, which is the easy way to hand a build to a +# colleague before there is a release to cut. + +on: + push: + tags: + - 'desktop-v*' + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - { os: macos-latest, name: macOS, target: '--mac' } + - { os: windows-latest, name: Windows, target: '--win' } + - { os: ubuntu-latest, name: Linux, target: '--linux' } + + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-node@v7 + with: + node-version: 22 + cache: npm + cache-dependency-path: desktop/package-lock.json + + - name: Install dependencies + working-directory: desktop + run: npm ci + + - name: Self-test the SSH tunnel transport + # Runs a real SSH server in-process, so it needs a display-free Electron. + # xvfb is only required on Linux; the other runners have a window server. + working-directory: desktop + run: ${{ matrix.os == 'ubuntu-latest' && 'xvfb-run --auto-servernum npm run selftest:tunnel' || 'npm run selftest:tunnel' }} + shell: bash + + - name: Build installers + working-directory: desktop + env: + # Signing is skipped when these are unset; electron-builder warns and + # produces unsigned artifacts rather than failing the build. + CSC_LINK: ${{ secrets.DESKTOP_CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.DESKTOP_CSC_KEY_PASSWORD }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + run: npx electron-builder ${{ matrix.target }} --publish never + + - uses: actions/upload-artifact@v4 + with: + name: deepsql-desktop-${{ matrix.name }} + if-no-files-found: error + path: | + desktop/release/*.dmg + desktop/release/*.zip + desktop/release/*.exe + desktop/release/*.AppImage + desktop/release/*.deb + desktop/release/*.rpm + + release: + name: attach to release + needs: build + if: startsWith(github.ref, 'refs/tags/desktop-v') + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + path: artifacts + merge-multiple: true + + - uses: softprops/action-gh-release@v2 + with: + files: artifacts/* + fail_on_unmatched_files: true diff --git a/AGENTS.md b/AGENTS.md index 342b4e3..7d5e9f0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -110,6 +110,27 @@ User Message → ChatController → SpringAIChatService - **UI state**: Zustand stores with selector hooks (`useActiveTab`, `useDashboardActions`) - **Independent chat threads**: Per-tab, per-connection, stored in localStorage +## Desktop Client (Electron) + +`desktop/` is a standalone Electron app (its own `package.json`, not part of the +root npm project). It is a **thin client**: it never bundles the React frontend, +it navigates a `WebContentsView` at the real DeepSQL origin, so the UI is always +the version the server runs. Two transports resolve to that origin — direct TLS, +or an in-process SSH local forward (`ssh2`, no `ssh` binary needed). + +| Path | Purpose | +|------|---------| +| `desktop/src/main/transport.js` | Transport manager: connect/disconnect/health per profile | +| `desktop/src/main/tunnel.js` | SSH local forward, host-key TOFU-then-strict, auto-reconnect | +| `desktop/src/main/tls.js` | Cert policy (system / pinned / custom CA / TOFU) for Node **and** Chromium | +| `desktop/src/main/profiles.js` | Connection profiles; secrets only as `safeStorage` ciphertext | +| `desktop/src/main/windows/workspace.js` | Frameless shell: native chrome + embedded DeepSQL view | +| `desktop/src/renderer/shared/theme.css` | Mirrors `src/index.css` tokens — keep in step | + +No backend change was needed: `docker/nginx/default.conf` already serves the SPA, +`/api` and `/agent-api` from one origin, which is what makes the thin-client +model work without CORS or cookie special-casing. + ## Performance & Safety Guardrails - Log size cap (500MB) via stream wrappers diff --git a/CLAUDE.md b/CLAUDE.md index 572a050..dffa41b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -93,6 +93,72 @@ mcp/ # DeepSQL Phase 1 MCP server (Node stdio wrapper around back agent/ # DeepSQL Agent customization (persona, skills, skins; customized Hermes runtime) ``` +## Desktop Client (`desktop/`) + +Cross-platform Electron client for a self-hosted DeepSQL VM. **Separate npm +project** — `cd desktop && npm install`, not part of the root `package.json`. + +```bash +cd desktop +npm start # run npm run dev # run with DevTools +npm run dist:mac # dmg + zip (arm64 + x64), also :win / :linux +npm run smoke -- --url https://deepsql.example.com # headless connection check +npm run selftest:tunnel # end-to-end SSH tunnel test (in-process SSH server) +``` + +**It is a thin client and deliberately does not bundle the React frontend.** It +navigates a `WebContentsView` at the real DeepSQL origin, so the UI is always the +version the VM is running — no bundle/backend skew, and no second copy of 40+ +tabs to maintain. This works with **zero backend changes** because +`docker/nginx/default.conf` already serves the SPA, `/api` and `/agent-api` from +one origin: cookies, CORS and SSE behave exactly as in a browser. Do not +"improve" this by bundling `dist/` — that reintroduces CORS, `SameSite`, and +version-skew problems the current design does not have. + +**Two transports, one abstraction.** Both resolve to an *origin*, so nothing +downstream of `desktop/src/main/transport.js` knows which is in use: + +- **Direct TLS** — the VM's HTTPS origin. Four certificate modes (`system`, + `pinned`, `custom-ca`, `insecure`/TOFU), applied to **both** the Node health + probe and the Chromium session (`tls.applyToSession`). Applying it to only one + gives a connection that tests green but renders a certificate error. +- **SSH tunnel** — `ssh2` local forward, loopback-bound, no `ssh` binary needed. + The local port is *sticky* across launches on purpose: the origin includes the + port, and a fresh random port would silently reset the web app's + `localStorage`. `http://127.0.0.1:*` is a Chromium secure context, so the + backend's `Secure` cookies still work over the tunnel. **Forward to the + frontend container (3000), not a host reverse proxy on :80** — that proxy + matches on `server_name`, a tunnel arrives with `Host: 127.0.0.1:`, + and the request lands on the default vhost as a 404 that reads like a broken + backend. The container's nginx uses `server_name _` and answers any Host. + +Three non-obvious things, all found the hard way: + +1. **`Client.connect({ privateKey })` must get the raw key material, not the + object `sshUtils.parseKey` returns.** Handed a parsed key, ssh2 silently + never offers the publickey method and the server replies with a bare + authentication failure — a symptom that points at the VM's `authorized_keys` + rather than at a type mismatch on our side. `loadPrivateKey` parses only to + produce good error messages and returns the buffer. +2. **Authentication succeeding says nothing about forwarding being allowed.** + A hardened sshd (`AllowTcpForwarding no`) accepts the login and refuses every + `direct-tcpip` channel; the failure otherwise surfaces as "socket hang up" on + the first browser request, pointing nowhere near sshd. `verifyForwarding()` + opens and closes one channel right after auth and classifies the refusal by + SSH reason code — 1 (`ADMINISTRATIVELY_PROHIBITED`, verified against real + OpenSSH) names `AllowTcpForwarding`, 2 (`CONNECT_FAILED`) means nothing is + listening on the remote port. +3. **Only a session that once reached `ready` may be reconnected.** Gating + reconnects on `everReady` is what stops a connect that fails on + authentication from retrying forever behind a caller that already surfaced + the error. + +Secrets (key passphrases, SSH passwords) are stored as `safeStorage` ciphertext; +where no OS keychain exists nothing is written to disk and the launcher says so. +Each profile gets its own session partition, so two DeepSQL servers never share +cookies. `.github/workflows/desktop-release.yml` builds all three platforms on +their native runners. See `desktop/README.md` for the full picture. + ## MCP Server - `mcp/deepsql-phase1-server.js` implements a Phase 1 stdio MCP server for internal rollout. diff --git a/desktop/.gitignore b/desktop/.gitignore new file mode 100644 index 0000000..dad03f4 --- /dev/null +++ b/desktop/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +release/ +build/icon.iconset/ +*.log diff --git a/desktop/README.md b/desktop/README.md new file mode 100644 index 0000000..08f0b3e --- /dev/null +++ b/desktop/README.md @@ -0,0 +1,210 @@ +# DeepSQL Desktop + +A cross-platform desktop client for a self-hosted DeepSQL server. It connects to +the VM (or bare metal) running the DeepSQL stack either **directly over TLS** or +through an **SSH tunnel**, and presents the DeepSQL UI in a native window with +connection management, health, and transport status built into the chrome. + +``` +┌────────────────── DeepSQL.app ──────────────────┐ +│ Launcher Workspace window │ +│ (connections) ┌──────────────────────────┐ │ +│ │ native chrome ● 170 ms │ │ +│ ├──────────────────────────┤ │ +│ │ the DeepSQL web UI │ │ +│ │ (WebContentsView) │ │ +│ └──────────────────────────┘ │ +└──────────┬───────────────────────┬───────────────┘ + │ TLS │ SSH tunnel + ▼ ▼ + https://deepsql.example.com 127.0.0.1:PORT ⇢ ssh ⇢ VM:3000 +``` + +## Design: a thin client, not a second frontend + +The client **does not bundle a copy of the DeepSQL web app**. It navigates an +embedded `WebContentsView` at the real DeepSQL origin. Consequences worth +knowing: + +- The UI is always the exact version the VM is running. There is no + bundle/backend skew and no second copy of 40+ tabs to keep in step. +- Cookies, CORS and SSE behave exactly as in a browser, because the app is + served from one origin — `docker/nginx/default.conf` already fronts `/api` + and `/agent-api` behind the frontend container. No backend change is needed + to support the desktop client. +- Everything the client adds is what a browser tab cannot show: which VM you + are on, how you are reaching it, and whether that path is healthy. + +Both transports resolve to the same thing — an origin — so nothing downstream +of the transport layer knows or cares which one is in use. + +## Install + +### From a release build + +| Platform | Artifact | +| --- | --- | +| macOS (Apple Silicon / Intel) | `DeepSQL--arm64.dmg`, `-x64.dmg` | +| Windows | `DeepSQL Setup .exe` (NSIS), portable `.exe` | +| Linux | `.AppImage`, `.deb`, `.rpm` | + +macOS builds are unsigned unless you supply signing credentials, so the first +launch needs **right-click → Open** (or `xattr -dr com.apple.quarantine +/Applications/DeepSQL.app`). + +### From source + +```bash +cd desktop +npm install +npm start # run the app +npm run dev # run with DevTools open +``` + +## Building installers + +```bash +npm run icons # regenerate build/icon.png from build/icon.svg +npm run dist:mac # dmg + zip, arm64 and x64 +npm run dist:win # nsis + portable, x64 and arm64 +npm run dist:linux # AppImage + deb + rpm +npm run dist # every target this host can build +``` + +Artifacts land in `desktop/release/`. Cross-building is limited by the host: +Windows targets need Wine on macOS/Linux, and Linux targets are most reliable in +the `electron-builder` Docker image. Building each platform on its own CI runner +is the low-friction option. + +**Code signing** is off by default. Set the standard electron-builder +environment variables to enable it: + +- macOS: `CSC_LINK`, `CSC_KEY_PASSWORD`, plus `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, `APPLE_TEAM_ID` for notarisation. +- Windows: `CSC_LINK`, `CSC_KEY_PASSWORD` (or an Azure Trusted Signing config). + +**Auto-update** is opt-in. `package.json` sets `"publish": null`, so no update +feed is baked in and the updater no-ops. To enable it, either set a `publish` +target (GitHub Releases, S3, generic) before building, or point +`DEEPSQL_UPDATE_FEED` at a generic feed URL at runtime. + +## Connecting + +### Direct over TLS + +Enter the origin that serves the DeepSQL UI — the same URL you would open in a +browser. Certificate verification has four modes: + +| Mode | Use when | +| --- | --- | +| **Publicly trusted** | The VM has a real hostname and a Let's Encrypt / commercial certificate. Default. | +| **Pinned certificate** | Self-signed certificate, or the server is only reachable by IP. Leave the fingerprint blank to pin whatever is presented on the first connection. | +| **Private CA bundle** | Corporate internal PKI. Point it at the CA `.pem`. | +| **Trust on first use** | Bootstrapping only. Accepts any certificate once, then pins it. Shown in red, and the workspace chrome badges the connection `UNVERIFIED`. | + +The pin applies to both the health probe (Node) and the embedded browser +(Chromium), so the UI is held to exactly the same rule as the connection check. + +### SSH tunnel + +Equivalent to `ssh -i key.pem -L :127.0.0.1:3000 ubuntu@vm`, but run +in-process — no `ssh` binary required, which matters on Windows. + +Use it when the DeepSQL ports are closed to the internet. The Compose stack only +publishes to the VM's own host, so a tunnel reaches them without exposing +anything publicly. + +- **Remote port** is DeepSQL *as seen from inside the VM*. Use `3000`, the + frontend container. Pointing it at a host reverse proxy on `:80` usually + returns 404: that proxy matches on `server_name`, and a tunnel arrives with + `Host: 127.0.0.1:`, which matches no vhost. The container's own nginx + uses `server_name _` and answers whatever Host it is given. +- **Local port** `0` picks a free port and then reuses it on later launches, so + the origin (and therefore the web app's `localStorage`) stays stable. +- The listener binds `127.0.0.1` only — never the LAN. +- Host keys are **trust on first use, then strict**. A changed host key aborts + the connection with both fingerprints shown rather than offering a dialog to + click through. If the VM was genuinely rebuilt, clear the pinned key in the + connection settings. + +`http://127.0.0.1:` is a secure context in Chromium, so the backend's +`Secure` session cookies are still accepted over the tunnel. + +## Security model + +- **Secrets** (key passphrases, SSH passwords) are encrypted with Electron + `safeStorage`, backed by Keychain / DPAPI / libsecret. On a machine with no + usable secret service, nothing is written to disk and the secret is kept in + memory for the session only — the launcher says so rather than pretending. +- **Session isolation**: each connection gets its own persistent partition + (`persist:deepsql-`), so signing into two DeepSQL servers never + crosses cookies or cached state. +- **Renderer hardening**: `contextIsolation` on, `nodeIntegration` off, the + content view sandboxed, `webview` attachment blocked, and permissions denied + by default except sanitised clipboard writes. +- **Navigation confinement**: the embedded view cannot leave the DeepSQL origin. + Same-origin popups (shared dashboards) open in a window on the same session; + everything else goes to the OS browser. +- **No credential proxying**: the client never sees database credentials. It + speaks to DeepSQL's own API surface exactly as a browser does. + +## Deep links + +`deepsql://connect?url=https://deepsql.example.com&name=Production` opens the +launcher with a connection pre-filled — a one-click onboarding link for an admin +to paste into internal docs. `transport=tunnel`, `sshHost` and `sshUser` are also +accepted. + +## Diagnostics + +```bash +# Check a server the same way the app does, without opening a window +npm run smoke -- --url https://deepsql.example.com +npm run smoke -- --ssh-host 20.29.48.144 --ssh-user ubuntu --key ~/keys/vm.pem + +# Exercise the tunnel end to end against a throwaway in-process SSH server +npm run selftest:tunnel +``` + +Logs are at `/logs/desktop.log`; the launcher footer has an **Open log +file** link. Connection profiles live in `/profiles.json` (mode 0600, +secrets stored only as `safeStorage` ciphertext). + +| Platform | userData | +| --- | --- | +| macOS | `~/Library/Application Support/DeepSQL` | +| Windows | `%APPDATA%\DeepSQL` | +| Linux | `~/.config/DeepSQL` | + +## Layout + +``` +src/ + main/ + index.js app lifecycle, single instance, deep links + config.js shared constants + profiles.js connection profiles + persistence + secrets.js safeStorage wrapper + transport.js transport manager (connect/disconnect/health) + tunnel.js SSH local forward (ssh2) + tls.js certificate policy for Node and Chromium + probe.js /api/actuator/health reachability check + ipc.js every renderer→main entry point + menu.js, updater.js, logger.js + windows/ + launcher.js connection manager window + workspace.js frameless shell: native chrome + DeepSQL view + preload/ narrow contextBridge APIs + renderer/ + shared/theme.css DeepSQL design tokens (mirrors src/index.css) + launcher/ connection manager UI + chrome/ workspace top chrome +scripts/ + generate-icons.js SVG → build/icon.png via Electron + smoke.js headless connection check + tunnel-selftest.js end-to-end SSH tunnel test +``` + +The renderers are plain HTML/CSS/JS with no build step: they are chrome around +an IPC surface, and the DeepSQL React app they wrap is loaded from the server, +not reimplemented. `renderer/shared/theme.css` mirrors the tokens in the web +app's `src/index.css` — keep the two in step if the palette moves. diff --git a/desktop/build/entitlements.mac.plist b/desktop/build/entitlements.mac.plist new file mode 100644 index 0000000..8078085 --- /dev/null +++ b/desktop/build/entitlements.mac.plist @@ -0,0 +1,22 @@ + + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + com.apple.security.network.client + + + com.apple.security.network.server + + + com.apple.security.files.user-selected.read-only + + + diff --git a/desktop/build/icon.png b/desktop/build/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..109c8c89064e0353d867ab18820b24a02742205e GIT binary patch literal 197185 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

QPUE&yG;`Rqb|X9I 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

n(*P5Y6bL_1ww6|#@GM0D>};o! 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

7K|{{m@-RVJiqo$ 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 q{3ixjeHdnGiz30l{IQYEb3 + + + + + + + + diff --git a/desktop/package-lock.json b/desktop/package-lock.json new file mode 100644 index 0000000..f0b6404 --- /dev/null +++ b/desktop/package-lock.json @@ -0,0 +1,3712 @@ +{ + "name": "deepsql-desktop", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "deepsql-desktop", + "version": "0.1.0", + "license": "Apache-2.0", + "dependencies": { + "electron-updater": "^6.8.9", + "ssh2": "^1.17.0" + }, + "devDependencies": { + "electron": "^43.2.0", + "electron-builder": "^26.15.3" + } + }, + "node_modules/@electron-internal/extract-zip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron-internal/extract-zip/-/extract-zip-1.0.5.tgz", + "integrity": "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA==", + "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.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "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.1.0", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-5.1.0.tgz", + "integrity": "sha512-3kSBtG8ObcTVfXanm5vVJ6UnBLEVmVsRk1M+vGqCuMBV+XLCbJYuWQful+yIy0GQDsSlK0kHEriEHn7SPk4EnA==", + "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.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "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.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "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==", + "license": "Python-2.0" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/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/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/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.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "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/buildcheck": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.7.tgz", + "integrity": "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA==", + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "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==", + "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/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "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==", + "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.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "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.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-43.2.0.tgz", + "integrity": "sha512-80zvrgG7ZRXD+tD0IyLvrnN9n+veSxadMRsMaC9wKKP3iUbtC7rGM8+dVuCmOb0Rrwwv8ESW4awnUZh9Hbp1fA==", + "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-updater": { + "version": "6.8.9", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.8.9.tgz", + "integrity": "sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig==", + "license": "MIT", + "dependencies": { + "builder-util-runtime": "9.7.0", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "~7.7.3", + "tiny-typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "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.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "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==", + "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.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "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==", + "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.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "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==", + "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==", + "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/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "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.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "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==", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.28.0.tgz", + "integrity": "sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==", + "license": "MIT", + "optional": true + }, + "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.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "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.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "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/ssh2": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", + "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", + "hasInstallScript": true, + "dependencies": { + "asn1": "^0.2.6", + "bcrypt-pbkdf": "^1.0.2" + }, + "engines": { + "node": ">=10.16.0" + }, + "optionalDependencies": { + "cpu-features": "~0.0.10", + "nan": "^2.23.0" + } + }, + "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.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "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/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "license": "MIT" + }, + "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/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, + "node_modules/type-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.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", + "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "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==", + "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/desktop/package.json b/desktop/package.json new file mode 100644 index 0000000..52211c6 --- /dev/null +++ b/desktop/package.json @@ -0,0 +1,162 @@ +{ + "name": "deepsql-desktop", + "productName": "DeepSQL", + "version": "0.1.0", + "private": true, + "description": "DeepSQL desktop client — connect to a self-hosted DeepSQL VM over TLS or an SSH tunnel.", + "license": "Apache-2.0", + "author": { + "name": "DeepSQL", + "email": "support@deepsql.local" + }, + "type": "commonjs", + "main": "src/main/index.js", + "scripts": { + "start": "electron .", + "dev": "DEEPSQL_DESKTOP_DEV=1 electron .", + "icons": "electron scripts/generate-icons.js", + "pack": "electron-builder --dir", + "dist": "electron-builder", + "dist:mac": "electron-builder --mac", + "dist:win": "electron-builder --win", + "dist:linux": "electron-builder --linux", + "dist:all": "electron-builder --mac --win --linux", + "smoke": "electron scripts/smoke.js", + "selftest:tunnel": "electron scripts/tunnel-selftest.js" + }, + "dependencies": { + "electron-updater": "^6.8.9", + "ssh2": "^1.17.0" + }, + "devDependencies": { + "electron": "^43.2.0", + "electron-builder": "^26.15.3" + }, + "build": { + "appId": "com.deepsql.desktop", + "productName": "DeepSQL", + "copyright": "Copyright © DeepSQL", + "directories": { + "output": "release", + "buildResources": "build" + }, + "files": [ + "src/**/*", + "build/icon.png", + "!**/*.map" + ], + "protocols": [ + { + "name": "DeepSQL", + "schemes": [ + "deepsql" + ] + } + ], + "asar": true, + "mac": { + "category": "public.app-category.developer-tools", + "target": [ + { + "target": "dmg", + "arch": [ + "arm64", + "x64" + ] + }, + { + "target": "zip", + "arch": [ + "arm64", + "x64" + ] + } + ], + "icon": "build/icon.png", + "hardenedRuntime": true, + "gatekeeperAssess": false, + "entitlements": "build/entitlements.mac.plist", + "entitlementsInherit": "build/entitlements.mac.plist", + "extendInfo": { + "NSHumanReadableCopyright": "Copyright © DeepSQL" + } + }, + "dmg": { + "title": "DeepSQL ${version}", + "contents": [ + { + "x": 140, + "y": 200, + "type": "file" + }, + { + "x": 400, + "y": 200, + "type": "link", + "path": "/Applications" + } + ] + }, + "win": { + "target": [ + { + "target": "nsis", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "portable", + "arch": [ + "x64" + ] + } + ], + "icon": "build/icon.png" + }, + "nsis": { + "oneClick": false, + "perMachine": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "createStartMenuShortcut": true, + "shortcutName": "DeepSQL" + }, + "linux": { + "target": [ + { + "target": "AppImage", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "deb", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "rpm", + "arch": [ + "x64" + ] + } + ], + "icon": "build/icon.png", + "category": "Development", + "maintainer": "DeepSQL ", + "desktop": { + "entry": { + "Name": "DeepSQL", + "Comment": "AI-powered Database Performance Assistant", + "MimeType": "x-scheme-handler/deepsql" + } + } + }, + "publish": null + } +} diff --git a/desktop/scripts/generate-icons.js b/desktop/scripts/generate-icons.js new file mode 100644 index 0000000..db26365 --- /dev/null +++ b/desktop/scripts/generate-icons.js @@ -0,0 +1,52 @@ +'use strict'; + +/** + * Rasterise build/icon.svg to build/icon.png (1024×1024). + * + * Run with `npm run icons`. It uses Electron's own Chromium rather than + * ImageMagick/rsvg so contributors on any OS can regenerate the icon with the + * dependencies already in this package. electron-builder derives the .icns and + * .ico it needs from that single PNG at package time. + */ + +const fs = require('node:fs'); +const path = require('node:path'); +const { app, BrowserWindow, nativeImage } = require('electron'); + +const SIZE = 1024; +const buildDir = path.join(__dirname, '..', 'build'); +const svgPath = path.join(buildDir, 'icon.svg'); +const pngPath = path.join(buildDir, 'icon.png'); + +app.disableHardwareAcceleration(); + +app.whenReady().then(async () => { + const svg = fs.readFileSync(svgPath, 'utf8'); + const page = ` + ${svg}`; + + const window = new BrowserWindow({ + width: SIZE, + height: SIZE, + show: false, + transparent: true, + frame: false, + webPreferences: { offscreen: true }, + }); + + await window.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(page)}`); + const image = await window.webContents.capturePage({ + x: 0, + y: 0, + width: SIZE, + height: SIZE, + }); + + const png = nativeImage.createFromBuffer(image.toPNG()).toPNG(); + fs.writeFileSync(pngPath, png); + process.stdout.write(`wrote ${pngPath} (${SIZE}x${SIZE}, ${png.length} bytes)\n`); + + window.destroy(); + app.quit(); +}); diff --git a/desktop/scripts/smoke.js b/desktop/scripts/smoke.js new file mode 100644 index 0000000..bb51b98 --- /dev/null +++ b/desktop/scripts/smoke.js @@ -0,0 +1,100 @@ +'use strict'; + +/** + * Headless connection check — the same transport code the app uses, without a + * window. Handy for diagnosing a VM from a terminal or CI before shipping a + * profile to users. + * + * npm run smoke -- --url https://deepsql.example.com + * npm run smoke -- --url https://10.0.0.5 --tls pinned + * npm run smoke -- --ssh-host 20.29.48.144 --ssh-user ubuntu \ + * --key ~/keys/vm.pem [--passphrase secret] [--remote-port 80] + * + * It runs against a throwaway userData directory so it never touches the + * profiles or keychain entries of the installed app. + */ + +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); +const { app } = require('electron'); + +const tmpUserData = fs.mkdtempSync(path.join(os.tmpdir(), 'deepsql-smoke-')); +app.setPath('userData', tmpUserData); + +const args = parseArgs(process.argv.slice(2)); + +app.whenReady().then(async () => { + const profiles = require('../src/main/profiles'); + const transport = require('../src/main/transport'); + + const useTunnel = Boolean(args['ssh-host']); + const profile = profiles.upsert({ + name: 'smoke', + transport: useTunnel ? 'tunnel' : 'direct', + url: args.url || '', + tls: { mode: args.tls || 'system', fingerprint: args.fingerprint || '', caPath: args.ca || '' }, + ssh: { + host: args['ssh-host'] || '', + port: args['ssh-port'] || 22, + username: args['ssh-user'] || 'ubuntu', + authMethod: args.key ? 'key' : args.password ? 'password' : 'agent', + privateKeyPath: args.key ? expand(args.key) : '', + passphrase: args.passphrase, + password: args.password, + remoteHost: args['remote-host'] || '127.0.0.1', + remotePort: args['remote-port'] || 80, + remoteScheme: args['remote-scheme'] || 'http', + localPort: 0, + }, + }); + + transport.on('status', (event) => { + if (event.detail) log(` ${event.detail}`); + }); + + log(`transport : ${profile.transport}`); + log(useTunnel ? `ssh : ${profile.ssh.username}@${profile.ssh.host}` : `url : ${profile.url}`); + + const result = await transport.test(profile.id); + + if (result.ok) { + log(''); + log(' OK'); + log(` origin : ${result.origin}`); + log(` latency : ${result.latencyMs} ms`); + if (result.certificateFingerprint) log(` cert : ${result.certificateFingerprint}`); + if (result.hostKeyFingerprint) log(` host key : ${result.hostKeyFingerprint}`); + } else { + log(''); + log(` FAILED (${result.code})`); + log(` ${result.detail}`); + } + + fs.rmSync(tmpUserData, { recursive: true, force: true }); + app.exit(result.ok ? 0 : 1); +}); + +function parseArgs(argv) { + const out = {}; + for (let i = 0; i < argv.length; i += 1) { + if (!argv[i].startsWith('--')) continue; + const key = argv[i].slice(2); + const next = argv[i + 1]; + if (next === undefined || next.startsWith('--')) { + out[key] = true; + } else { + out[key] = next; + i += 1; + } + } + return out; +} + +function expand(p) { + return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p; +} + +function log(line) { + process.stdout.write(`${line}\n`); +} diff --git a/desktop/scripts/tunnel-selftest.js b/desktop/scripts/tunnel-selftest.js new file mode 100644 index 0000000..4029935 --- /dev/null +++ b/desktop/scripts/tunnel-selftest.js @@ -0,0 +1,270 @@ +'use strict'; + +/** + * End-to-end self-test for the SSH tunnel transport. + * + * Stands up a throwaway SSH server and a fake DeepSQL health endpoint on + * loopback, then drives the real SshTunnel + probe code against them. It + * exercises the parts that are otherwise only reachable with a live VM and a + * private key: key parsing, publickey auth, host-key pinning, direct-tcpip + * forwarding, and the sticky local port. + * + * npm run selftest:tunnel + */ + +const crypto = require('node:crypto'); +const fs = require('node:fs'); +const http = require('node:http'); +const net = require('node:net'); +const os = require('node:os'); +const path = require('node:path'); +const { app } = require('electron'); + +const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'deepsql-tunnel-test-')); +app.setPath('userData', tmpDir); + +const results = []; +function check(name, condition, detail = '') { + results.push({ name, ok: Boolean(condition), detail }); + process.stdout.write(` ${condition ? 'PASS' : 'FAIL'} ${name}${detail ? ` — ${detail}` : ''}\n`); +} + +app.whenReady().then(async () => { + const { Server } = require('ssh2'); + const { SshTunnel, hostKeyFingerprint } = require('../src/main/tunnel'); + const { probe } = require('../src/main/probe'); + + // ── Fixtures ─────────────────────────────────────────────────────────── + const { privateKey, publicKeyPem } = generateRsaPem(); + const keyPath = path.join(tmpDir, 'test-key.pem'); + fs.writeFileSync(keyPath, privateKey, { mode: 0o600 }); + + // Stands in for the DeepSQL nginx inside the VM. + const upstream = http.createServer((req, res) => { + if (req.url === '/api/actuator/health') { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end('{"status":"UP"}'); + return; + } + res.writeHead(404).end(); + }); + await listen(upstream, 0, '127.0.0.1'); + const upstreamPort = upstream.address().port; + + let forwardedTo = null; + // Flipped on to emulate a VM with `AllowTcpForwarding no`: login succeeds, + // every direct-tcpip channel is refused. + let refuseForwarding = false; + const sshServer = new Server({ hostKeys: [privateKey] }, (client) => { + client.on('authentication', (ctx) => { + // Accepting any publickey is fine here: the point is to exercise our + // client, not to be a real authenticator. + if (ctx.method === 'publickey') ctx.accept(); + else ctx.reject(['publickey']); + }); + client.on('ready', () => { + client.on('tcpip', (accept, reject, info) => { + if (refuseForwarding) { + // 1 = ADMINISTRATIVELY_PROHIBITED. Verified against a real OpenSSH + // server with `AllowTcpForwarding no`, which sends exactly this with + // the description "open failed". A bare reject() would default to + // CONNECT_FAILED and test the wrong branch. + reject(1, 'open failed'); + return; + } + forwardedTo = `${info.destIP}:${info.destPort}`; + const channel = accept(); + const socket = net.connect(info.destPort, info.destIP, () => { + channel.pipe(socket).pipe(channel); + }); + socket.on('error', () => channel.end()); + }); + }); + client.on('error', () => {}); + }); + await listen(sshServer, 0, '127.0.0.1'); + const sshPort = sshServer.address().port; + + const expectedHostKey = hostKeyFingerprint(publicKeyPem.sshWireFormat); + + // ── 1. First connection pins the host key and forwards traffic ───────── + const profile = makeProfile({ keyPath, sshPort, upstreamPort }); + const tunnel = new SshTunnel(profile, {}); + const { localPort, hostKeyFingerprint: seenHostKey } = await tunnel.start(); + + check('tunnel binds a loopback port', localPort > 0, `port ${localPort}`); + check( + 'host key fingerprint matches the server key', + seenHostKey === expectedHostKey, + seenHostKey, + ); + + const health = await probe(`http://127.0.0.1:${localPort}`, profile); + check('health probe succeeds through the tunnel', health.ok, health.detail); + check( + 'traffic is forwarded to the configured remote endpoint', + forwardedTo === `127.0.0.1:${upstreamPort}`, + forwardedTo, + ); + + // The listener must never be reachable from anything but loopback. + check( + 'listener is bound to loopback only', + tunnel.server.address().address === '127.0.0.1', + tunnel.server.address().address, + ); + + await tunnel.stop(); + check('stop() releases the local port', await portIsFree(localPort)); + + // ── 2. A changed host key is refused ─────────────────────────────────── + const tamperedProfile = makeProfile({ keyPath, sshPort, upstreamPort }); + tamperedProfile.ssh.hostKeyFingerprint = 'SHA256:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'; + const strictTunnel = new SshTunnel(tamperedProfile, {}); + let rejected = null; + try { + await strictTunnel.start(); + } catch (err) { + rejected = err; + } + await strictTunnel.stop(); + check( + 'mismatched host key aborts the connection', + rejected !== null, + rejected ? rejected.code : 'connection was allowed', + ); + + // ── 3. A refused forwarding channel fails before the listener binds ──── + // Regression guard: this used to surface as "socket hang up" only once the + // browser made a request, with nothing pointing at the SSH layer at all. + // + // ssh2's server-side reject() takes no arguments and always answers + // CONNECT_FAILED, so the live half of this test can only cover that branch. + // The ADMINISTRATIVELY_PROHIBITED branch — what a real `AllowTcpForwarding no` + // server sends — is checked directly below against the error shape observed + // from OpenSSH: `{ reason: 1, message: '(SSH) Channel open failure: open failed' }`. + refuseForwarding = true; + const deniedProfile = makeProfile({ keyPath, sshPort, upstreamPort }); + const deniedTunnel = new SshTunnel(deniedProfile, {}); + let denied = null; + try { + await deniedTunnel.start(); + } catch (err) { + denied = err; + } + await deniedTunnel.stop(); + check( + 'a refused channel fails start() instead of the later HTTP request', + denied?.code === 'remote-port-closed', + denied ? denied.code : 'start() succeeded', + ); + check( + 'the failure never leaves a listener bound', + deniedTunnel.server === null || deniedTunnel.localPort === null, + `server=${deniedTunnel.server === null ? 'null' : 'bound'}`, + ); + refuseForwarding = false; + + const classifier = new SshTunnel(makeProfile({ keyPath, sshPort, upstreamPort }), {}); + const prohibited = classifier.translateChannelError({ + reason: 1, + message: '(SSH) Channel open failure: open failed', + }); + check( + 'AllowTcpForwarding=no is named as the cause', + prohibited.code === 'forwarding-denied' && /allowtcpforwarding/i.test(prohibited.message), + prohibited.code, + ); + check( + 'a closed remote port is distinguished from a forwarding ban', + classifier.translateChannelError({ reason: 2 }).code === 'remote-port-closed', + ); + + // ── 4. Missing key file fails with an actionable message ─────────────── + const noKeyProfile = makeProfile({ keyPath: path.join(tmpDir, 'nope.pem'), sshPort, upstreamPort }); + let keyError = null; + try { + await new SshTunnel(noKeyProfile, {}).start(); + } catch (err) { + keyError = err; + } + check('missing key file is reported clearly', keyError?.code === 'key-unreadable', keyError?.code); + + // ── 5. Teardown ──────────────────────────────────────────────────────── + sshServer.close(); + upstream.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + + const failed = results.filter((r) => !r.ok).length; + process.stdout.write(`\n${results.length - failed}/${results.length} checks passed\n`); + app.exit(failed === 0 ? 0 : 1); +}); + +function makeProfile({ keyPath, sshPort, upstreamPort }) { + return { + id: 'selftest', + name: 'selftest', + transport: 'tunnel', + tls: { mode: 'system' }, + ssh: { + host: '127.0.0.1', + port: sshPort, + username: 'tester', + authMethod: 'key', + privateKeyPath: keyPath, + remoteHost: '127.0.0.1', + remotePort: upstreamPort, + remoteScheme: 'http', + localPort: 0, + stickyLocalPort: 0, + hostKeyFingerprint: '', + }, + }; +} + +function generateRsaPem() { + const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', { + modulusLength: 2048, + privateKeyEncoding: { type: 'pkcs1', format: 'pem' }, + publicKeyEncoding: { type: 'pkcs1', format: 'der' }, + }); + // ssh2 fingerprints the SSH wire format of the public key, so rebuild it from + // the RSA modulus/exponent rather than trusting the DER encoding. + const jwk = crypto.createPublicKey(privateKey).export({ format: 'jwk' }); + const e = Buffer.from(jwk.e, 'base64url'); + const n = Buffer.from(jwk.n, 'base64url'); + const sshWireFormat = Buffer.concat([ + sshString(Buffer.from('ssh-rsa')), + sshString(prefixZeroIfSigned(e)), + sshString(prefixZeroIfSigned(n)), + ]); + return { privateKey, publicKeyPem: { der: publicKey, sshWireFormat } }; +} + +function sshString(buffer) { + const length = Buffer.alloc(4); + length.writeUInt32BE(buffer.length); + return Buffer.concat([length, buffer]); +} + +function prefixZeroIfSigned(buffer) { + return buffer[0] & 0x80 ? Buffer.concat([Buffer.from([0]), buffer]) : buffer; +} + +function listen(server, port, host) { + return new Promise((resolve, reject) => { + server.once('error', reject); + server.listen(port, host, () => resolve()); + }); +} + +function portIsFree(port) { + return new Promise((resolve) => { + const socket = net.connect(port, '127.0.0.1'); + socket.on('connect', () => { + socket.destroy(); + resolve(false); + }); + socket.on('error', () => resolve(true)); + }); +} diff --git a/desktop/src/main/config.js b/desktop/src/main/config.js new file mode 100644 index 0000000..30957bf --- /dev/null +++ b/desktop/src/main/config.js @@ -0,0 +1,50 @@ +'use strict'; + +/** + * Shared constants for the DeepSQL desktop client. + * + * The client is a *thin* client: it never bundles a copy of the DeepSQL web UI. + * It navigates a WebContentsView at the real DeepSQL origin (reached either + * directly over TLS or through an SSH tunnel), so the UI a user sees is always + * exactly the version their VM is running. There is no bundle/backend skew to + * manage, and cookies/CORS behave the same as they do in a browser because the + * app content is served from a single origin (the frontend nginx in + * docker/nginx/default.conf already fronts /api and /agent-api). + */ + +const path = require('node:path'); +const { app } = require('electron'); + +const IS_DEV = + process.env.DEEPSQL_DESKTOP_DEV === '1' || !app.isPackaged; + +// Health probe served by the Spring backend through the frontend nginx. +const HEALTH_PATH = '/api/actuator/health'; + +// How often the workspace re-probes the connection while a window is open. +const HEALTH_INTERVAL_MS = 20_000; + +// Height of the native top chrome above the embedded DeepSQL UI. +const CHROME_HEIGHT = 44; + +const RENDERER_DIR = path.join(__dirname, '..', 'renderer'); +const PRELOAD_DIR = path.join(__dirname, '..', 'preload'); + +const LAUNCHER_HTML = path.join(RENDERER_DIR, 'launcher', 'index.html'); +const CHROME_HTML = path.join(RENDERER_DIR, 'chrome', 'index.html'); +const LAUNCHER_PRELOAD = path.join(PRELOAD_DIR, 'launcher.js'); +const CHROME_PRELOAD = path.join(PRELOAD_DIR, 'chrome.js'); + +const PROTOCOL = 'deepsql'; + +module.exports = { + IS_DEV, + HEALTH_PATH, + HEALTH_INTERVAL_MS, + CHROME_HEIGHT, + LAUNCHER_HTML, + CHROME_HTML, + LAUNCHER_PRELOAD, + CHROME_PRELOAD, + PROTOCOL, +}; diff --git a/desktop/src/main/index.js b/desktop/src/main/index.js new file mode 100644 index 0000000..6d9cd07 --- /dev/null +++ b/desktop/src/main/index.js @@ -0,0 +1,139 @@ +'use strict'; + +/** + * DeepSQL desktop client — main process entry point. + * + * Lifecycle: launcher (pick a VM) → transport comes up (TLS or SSH tunnel) → + * workspace window opens on the resulting origin. Quitting tears every tunnel + * down; a leaked loopback listener would be a live hole into the VM. + */ + +const { app, BrowserWindow, shell } = require('electron'); + +const { PROTOCOL, IS_DEV } = require('./config'); +const ipc = require('./ipc'); +const menu = require('./menu'); +const updater = require('./updater'); +const launcher = require('./windows/launcher'); +const workspaces = require('./windows/workspace'); +const transport = require('./transport'); +const log = require('./logger'); + +// Two instances would fight over the same profiles.json and could bind the same +// sticky tunnel port; the second one just focuses the first. +if (!app.requestSingleInstanceLock()) { + app.quit(); +} else { + app.on('second-instance', (_event, argv) => { + const existing = launcher.get() || workspaces.all()[0]?.window; + if (existing) { + if (existing.isMinimized?.()) existing.restore(); + existing.focus(); + } else { + launcher.create(); + } + handleDeepLink(argv.find((arg) => arg.startsWith(`${PROTOCOL}://`))); + }); + + bootstrap(); +} + +function bootstrap() { + app.setName('DeepSQL'); + + if (process.defaultApp) { + // Dev: register the scheme with the electron binary + script path. + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [process.argv[1]]); + } + } else { + app.setAsDefaultProtocolClient(PROTOCOL); + } + + app.on('open-url', (event, url) => { + event.preventDefault(); + handleDeepLink(url); + }); + + app.whenReady().then(() => { + log.info('app', 'starting', { + version: app.getVersion(), + electron: process.versions.electron, + platform: `${process.platform}-${process.arch}`, + dev: IS_DEV, + }); + + ipc.register(); + menu.build(); + launcher.create(); + updater.init(); + handleDeepLinkFromArgv(); + + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0 && workspaces.all().length === 0) { + launcher.create(); + } + }); + }); + + app.on('window-all-closed', async () => { + await transport.disconnectAll(); + if (process.platform !== 'darwin') app.quit(); + }); + + app.on('before-quit', async (event) => { + if (transport.active.size === 0) return; + event.preventDefault(); + await transport.disconnectAll(); + app.quit(); + }); + + // Defence in depth: even if a view slipped past its own navigation guard, + // nothing may open a Node-enabled window or reach a non-http scheme. + app.on('web-contents-created', (_event, contents) => { + contents.on('will-attach-webview', (event) => event.preventDefault()); + contents.setWindowOpenHandler(({ url }) => { + if (/^https?:/i.test(url)) shell.openExternal(url); + return { action: 'deny' }; + }); + }); +} + +/** + * `deepsql://connect?url=https://vm.example.com&name=Prod` opens the launcher + * with a new profile pre-filled — the one-click "connect to our VM" link an + * admin can paste into onboarding docs. + */ +function handleDeepLink(rawUrl) { + if (!rawUrl) return; + let parsed; + try { + parsed = new URL(rawUrl); + } catch { + return; + } + if (parsed.protocol !== `${PROTOCOL}:`) return; + + const window = launcher.create(); + const payload = { + action: parsed.hostname || 'connect', + url: parsed.searchParams.get('url') || '', + name: parsed.searchParams.get('name') || '', + transport: parsed.searchParams.get('transport') === 'tunnel' ? 'tunnel' : 'direct', + sshHost: parsed.searchParams.get('sshHost') || '', + sshUser: parsed.searchParams.get('sshUser') || '', + }; + const send = () => window.webContents.send('deeplink', payload); + if (window.webContents.isLoading()) { + window.webContents.once('did-finish-load', send); + } else { + send(); + } + log.info('app', 'handled deep link', payload); +} + +/** Windows/Linux cold start with a protocol argument. */ +function handleDeepLinkFromArgv() { + const arg = process.argv.find((value) => value.startsWith(`${PROTOCOL}://`)); + if (arg) handleDeepLink(arg); +} diff --git a/desktop/src/main/ipc.js b/desktop/src/main/ipc.js new file mode 100644 index 0000000..610a42c --- /dev/null +++ b/desktop/src/main/ipc.js @@ -0,0 +1,177 @@ +'use strict'; + +/** Every renderer→main entry point in the app lives here. */ + +const { ipcMain, dialog, shell, app } = require('electron'); + +const profilesStore = require('./profiles'); +const secrets = require('./secrets'); +const transport = require('./transport'); +const launcher = require('./windows/launcher'); +const workspaces = require('./windows/workspace'); +const log = require('./logger'); + +function register() { + // ── App ──────────────────────────────────────────────────────────────── + ipcMain.handle('app:info', () => ({ + // Not app.getVersion(): under `electron + + diff --git a/desktop/src/renderer/launcher/index.html b/desktop/src/renderer/launcher/index.html new file mode 100644 index 0000000..3b7b923 --- /dev/null +++ b/desktop/src/renderer/launcher/index.html @@ -0,0 +1,252 @@ + + + + + + DeepSQL + + + + +
+ + + + +
+
+ +
+ +

Connect to your DeepSQL server

+

+ DeepSQL runs on your own VM or hardware. Point this client at it over TLS, or + tunnel in over SSH when the ports are closed to the internet. +

+ +
+ + +
+
+ + + + diff --git a/desktop/src/renderer/launcher/launcher.css b/desktop/src/renderer/launcher/launcher.css new file mode 100644 index 0000000..ede7aaa --- /dev/null +++ b/desktop/src/renderer/launcher/launcher.css @@ -0,0 +1,532 @@ +/* Launcher — the connection manager. Mirrors AppSidebar.module.css proportions + from the web app (220px rail, 1px #e5e7eb divider, 8px nav radii). */ + +.shell { + display: flex; + height: 100vh; + overflow: hidden; +} + +/* Draggable strip so a frameless/hidden-inset window can still be moved. */ +.drag-strip { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 38px; + -webkit-app-region: drag; + pointer-events: auto; +} + +.drag-strip * { + -webkit-app-region: no-drag; +} + +/* ── Sidebar ──────────────────────────────────────────────────────────── */ +.sidebar { + position: relative; + width: 248px; + min-width: 248px; + display: flex; + flex-direction: column; + background: var(--color-white); + border-right: 1px solid var(--color-border); +} + +.brand { + display: flex; + align-items: center; + gap: 10px; + padding: 46px 16px 12px; + flex-shrink: 0; +} + +.brand-mark { + width: 28px; + height: 28px; + background: var(--color-ink); + border-radius: 7px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.brand-text { + font-size: 15px; + font-weight: 600; + color: var(--color-ink); + letter-spacing: -0.01em; +} + +.rail-label { + padding: 10px 18px 6px; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + color: var(--color-light-5); +} + +.profile-list { + flex: 1; + overflow-y: auto; + padding: 0 8px 8px; + display: flex; + flex-direction: column; + gap: 1px; +} + +.profile-item { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + padding: 9px 10px; + border-radius: 8px; + text-align: left; + color: var(--color-light-6); + transition: background 0.1s, color 0.1s; +} + +.profile-item:hover { + background: var(--color-light-2); + color: var(--color-text); +} + +.profile-item.is-active { + background: var(--color-light-2); + color: var(--color-text); + font-weight: 500; +} + +.profile-dot { + width: 7px; + height: 7px; + border-radius: 999px; + background: var(--color-light-4); + flex-shrink: 0; +} + +.profile-dot.is-live { + background: var(--color-success); + box-shadow: 0 0 0 3px var(--color-success-soft); +} + +.profile-copy { + min-width: 0; + display: flex; + flex-direction: column; + line-height: 1.3; +} + +.profile-name { + font-size: 13.5px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.profile-sub { + font-size: 11.5px; + color: var(--color-light-5); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.sidebar-footer { + border-top: 1px solid var(--color-border); + padding: 10px 12px 12px; + flex-shrink: 0; +} + +.new-connection { + width: 100%; + justify-content: flex-start; + gap: 8px; + padding: 8px 10px; + color: var(--color-light-8); + font-size: 13.5px; + font-weight: 500; +} + +.app-meta { + margin-top: 8px; + padding: 0 4px; + font-size: 11px; + line-height: 1.5; + color: var(--color-light-5); +} + +.app-meta button { + padding: 0; + font-size: 11px; + color: var(--color-light-6); + text-decoration: underline; + background: none; +} + +.app-meta button:hover { + background: none; + color: var(--color-text); +} + +/* ── Detail pane ──────────────────────────────────────────────────────── */ +.pane { + position: relative; + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.pane-drag { + height: 30px; +} + +.empty-state { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 14px; + padding: 0 64px; +} + +.empty-mark { + width: 56px; + height: 56px; + border-radius: var(--radius-lg); + background: var(--color-white); + border: 1px solid var(--color-border); + box-shadow: var(--shadow-card); + display: flex; + align-items: center; + justify-content: center; +} + +.empty-state h1 { + margin: 0; + font-size: 20px; + font-weight: 600; + letter-spacing: -0.02em; +} + +.empty-state p { + margin: 0; + max-width: 440px; + color: var(--color-text-secondary); +} + +.empty-state .btn-primary { + margin-top: 8px; +} + +/* ── Editor ───────────────────────────────────────────────────────────── */ +.editor { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; +} + +.editor-head { + padding: 34px 32px 14px; + flex-shrink: 0; +} + +.editor-title-row { + display: flex; + align-items: center; + gap: 12px; +} + +.title-input { + flex: 1; + min-width: 0; + font-size: 21px; + font-weight: 600; + letter-spacing: -0.02em; + padding: 4px 8px; + margin-left: -8px; + border: 1px solid transparent; + background: transparent; + border-radius: var(--radius-sm); +} + +.title-input:hover { + border-color: var(--color-light-3); +} + +.title-input:focus { + background: var(--color-white); + border-color: var(--color-light-4); + box-shadow: none; +} + +.editor-subtitle { + margin: 4px 0 0; + font-size: 12.5px; + color: var(--color-light-5); +} + +.pill { + flex-shrink: 0; + display: inline-flex; + align-items: center; + gap: 6px; + padding: 4px 12px; + border-radius: var(--radius-button); + font-size: 12px; + font-weight: 500; + white-space: nowrap; +} + +.pill-idle { + background: var(--color-light-2); + color: var(--color-light-6); +} + +.pill-busy { + background: var(--color-warning-soft); + color: #92400e; +} + +.pill-live { + background: var(--color-success-soft); + color: #15803d; +} + +.pill-error { + background: var(--color-danger-soft); + color: var(--color-danger-text); +} + +.editor-body { + flex: 1; + min-height: 0; + overflow-y: auto; + padding: 6px 32px 24px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.card { + background: var(--color-white); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-card); + padding: 20px; + display: flex; + flex-direction: column; + gap: 16px; +} + +.card-head h2 { + margin: 0; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.02em; + text-transform: uppercase; + color: var(--color-light-6); +} + +.card-head-inner { + margin-top: 4px; + padding-top: 16px; + border-top: 1px solid var(--color-border); +} + +.segmented { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} + +.seg { + flex-direction: column; + align-items: flex-start; + gap: 3px; + padding: 13px 15px; + border: 1px solid var(--color-light-3); + border-radius: var(--radius-md); + background: var(--color-white); + text-align: left; + transition: border-color 0.12s, background 0.12s; +} + +.seg strong { + font-size: 13.5px; + font-weight: 600; + color: var(--color-text); +} + +.seg span { + font-size: 12px; + font-weight: 400; + color: var(--color-light-5); + line-height: 1.45; +} + +.seg:hover { + background: var(--color-white); + border-color: var(--color-light-4); +} + +.seg.is-selected { + border-color: var(--color-ink); + background: #fafafa; +} + +.field { + display: flex; + flex-direction: column; + gap: 6px; +} + +.field-label { + font-size: 11px; + font-weight: 600; + letter-spacing: 0.05em; + text-transform: uppercase; + color: var(--color-light-5); +} + +.field-label em { + font-style: normal; + font-weight: 400; + text-transform: none; + letter-spacing: 0; + color: var(--color-light-4); +} + +.field-hint { + font-size: 12px; + line-height: 1.5; + color: var(--color-light-5); +} + +.field-hint code, +.notice code, +code.mono { + font-family: var(--font-family-mono); + font-size: 11.5px; + background: var(--color-light-2); + padding: 1px 5px; + border-radius: 4px; + user-select: text; +} + +.grid-3 { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + gap: 12px; +} + +.file-row { + display: flex; + gap: 8px; +} + +.file-row input { + flex: 1; + min-width: 0; +} + +.notice { + font-size: 12.5px; + line-height: 1.55; + padding: 11px 14px; + border-radius: var(--radius-md); +} + +.notice-danger { + background: var(--color-danger-soft); + border: 1px solid var(--color-danger-border); + color: var(--color-danger-text); +} + +.notice-muted { + background: var(--color-light-2); + color: var(--color-light-6); +} + +.host-key { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 11px 14px; + background: var(--color-light-2); + border-radius: var(--radius-md); +} + +.host-key code { + display: block; + margin-top: 2px; + background: transparent; + padding: 0; + color: var(--color-light-8); + word-break: break-all; +} + +/* ── Footer ───────────────────────────────────────────────────────────── */ +.editor-foot { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 16px; + padding: 14px 32px; + background: var(--color-white); + border-top: 1px solid var(--color-border); +} + +.foot-left { + flex-shrink: 0; +} + +.foot-right { + display: flex; + gap: 10px; + flex-shrink: 0; +} + +.feedback { + flex: 1; + min-width: 0; + font-size: 12.5px; + line-height: 1.45; + color: var(--color-light-6); + user-select: text; +} + +.feedback.is-error { + color: var(--color-danger-text); +} + +.feedback.is-ok { + color: var(--color-success); +} + +.spinner { + display: inline-block; + width: 11px; + height: 11px; + margin-right: 7px; + vertical-align: -1px; + border: 1.5px solid currentColor; + border-top-color: transparent; + border-radius: 999px; + animation: spin 0.7s linear infinite; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} diff --git a/desktop/src/renderer/launcher/launcher.js b/desktop/src/renderer/launcher/launcher.js new file mode 100644 index 0000000..39167dc --- /dev/null +++ b/desktop/src/renderer/launcher/launcher.js @@ -0,0 +1,509 @@ +'use strict'; + +/* Launcher renderer. No framework on purpose: this is three screens of chrome + around an IPC surface, and a build step here would be a second toolchain to + keep alive for no gain. The DeepSQL app itself is React — it is loaded from + the server, not reimplemented. */ + +const api = window.deepsql; + +const el = (id) => document.getElementById(id); + +const dom = { + list: el('profile-list'), + meta: el('app-meta'), + empty: el('empty-state'), + editor: el('editor'), + subtitle: el('editor-subtitle'), + statusPill: el('status-pill'), + feedback: el('feedback'), + hostKeyRow: el('host-key-row'), + hostKeyValue: el('host-key-value'), + secretHint: el('secret-hint'), + fields: { + name: el('f-name'), + url: el('f-url'), + tlsMode: el('f-tls-mode'), + tlsFingerprint: el('f-tls-fingerprint'), + tlsCa: el('f-tls-ca'), + sshHost: el('f-ssh-host'), + sshPort: el('f-ssh-port'), + sshUser: el('f-ssh-user'), + sshAuth: el('f-ssh-auth'), + sshKey: el('f-ssh-key'), + sshPassphrase: el('f-ssh-passphrase'), + sshPassword: el('f-ssh-password'), + remoteHost: el('f-remote-host'), + remotePort: el('f-remote-port'), + localPort: el('f-local-port'), + }, +}; + +const state = { + profiles: [], + selectedId: null, + /** Unsaved new profile, held here until the first save. */ + draft: null, + transport: 'direct', + active: new Set(), + busy: false, + info: null, +}; + +// ── Rendering ──────────────────────────────────────────────────────────── + +function selected() { + if (state.draft) return state.draft; + return state.profiles.find((p) => p.id === state.selectedId) || null; +} + +function renderList() { + dom.list.replaceChildren(); + + for (const profile of state.profiles) { + const item = document.createElement('button'); + item.type = 'button'; + item.className = 'profile-item'; + if (!state.draft && profile.id === state.selectedId) item.classList.add('is-active'); + + const dot = document.createElement('span'); + dot.className = `profile-dot${state.active.has(profile.id) ? ' is-live' : ''}`; + + const copy = document.createElement('span'); + copy.className = 'profile-copy'; + const name = document.createElement('span'); + name.className = 'profile-name'; + name.textContent = profile.name; + const sub = document.createElement('span'); + sub.className = 'profile-sub'; + sub.textContent = describe(profile); + copy.append(name, sub); + + item.append(dot, copy); + item.addEventListener('click', () => select(profile.id)); + dom.list.append(item); + } + + if (state.draft) { + const item = document.createElement('button'); + item.type = 'button'; + item.className = 'profile-item is-active'; + const dot = document.createElement('span'); + dot.className = 'profile-dot'; + const copy = document.createElement('span'); + copy.className = 'profile-copy'; + const name = document.createElement('span'); + name.className = 'profile-name'; + name.textContent = state.draft.name || 'New connection'; + const sub = document.createElement('span'); + sub.className = 'profile-sub'; + sub.textContent = 'Unsaved'; + copy.append(name, sub); + item.append(dot, copy); + dom.list.append(item); + } +} + +function describe(profile) { + if (profile.transport === 'tunnel') { + const { username, host, remotePort } = profile.ssh; + return host ? `ssh ${username}@${host} → :${remotePort}` : 'SSH tunnel'; + } + try { + return new URL(profile.url).host; + } catch { + return 'No URL set'; + } +} + +function renderEditor() { + const profile = selected(); + const hasProfile = Boolean(profile); + dom.empty.hidden = hasProfile; + dom.editor.hidden = !hasProfile; + if (!profile) return; + + state.transport = profile.transport; + + dom.fields.name.value = profile.name || ''; + dom.fields.url.value = profile.url || ''; + dom.fields.tlsMode.value = profile.tls?.mode || 'system'; + dom.fields.tlsFingerprint.value = profile.tls?.fingerprint || ''; + dom.fields.tlsCa.value = profile.tls?.caPath || ''; + + const ssh = profile.ssh || {}; + dom.fields.sshHost.value = ssh.host || ''; + dom.fields.sshPort.value = ssh.port ?? 22; + dom.fields.sshUser.value = ssh.username || ''; + dom.fields.sshAuth.value = ssh.authMethod || 'key'; + dom.fields.sshKey.value = ssh.privateKeyPath || ''; + dom.fields.sshPassphrase.value = ''; + dom.fields.sshPassword.value = ''; + dom.fields.remoteHost.value = ssh.remoteHost || '127.0.0.1'; + dom.fields.remotePort.value = ssh.remotePort ?? 3000; + dom.fields.localPort.value = ssh.localPort ?? 0; + + dom.hostKeyRow.hidden = !ssh.hostKeyFingerprint; + dom.hostKeyValue.textContent = ssh.hostKeyFingerprint || ''; + + dom.secretHint.textContent = ssh.hasStoredPassphrase + ? state.info?.keychainAvailable + ? 'A passphrase is saved in your OS keychain. Type here only to replace it.' + : 'A passphrase is held for this session only — the OS keychain is unavailable.' + : ''; + + dom.subtitle.textContent = profile.lastConnectedAt + ? `Last connected ${formatWhen(profile.lastConnectedAt)}` + : state.draft + ? 'Not saved yet' + : 'Never connected'; + + el('delete-profile').hidden = Boolean(state.draft); + + syncVisibility(); + setStatus( + state.active.has(profile.id) ? 'live' : 'idle', + state.active.has(profile.id) ? 'Connected' : 'Not connected', + ); +} + +/** Show only the fields the current transport / TLS mode / auth method needs. */ +function syncVisibility() { + const transport = state.transport; + for (const seg of document.querySelectorAll('.seg')) { + seg.classList.toggle('is-selected', seg.dataset.transport === transport); + } + for (const panel of document.querySelectorAll('[data-panel]')) { + panel.hidden = panel.dataset.panel !== transport; + } + const tlsMode = dom.fields.tlsMode.value; + for (const node of document.querySelectorAll('[data-tls]')) { + node.hidden = node.dataset.tls !== tlsMode; + } + const auth = dom.fields.sshAuth.value; + for (const node of document.querySelectorAll('[data-auth]')) { + node.hidden = node.dataset.auth !== auth; + } +} + +function setStatus(kind, text) { + dom.statusPill.className = `pill pill-${kind}`; + dom.statusPill.textContent = text; +} + +function say(message, kind = '') { + dom.feedback.className = `feedback${kind ? ` is-${kind}` : ''}`; + dom.feedback.replaceChildren(); + if (kind === 'busy') { + const spinner = document.createElement('span'); + spinner.className = 'spinner'; + dom.feedback.append(spinner); + } + dom.feedback.append(document.createTextNode(message)); +} + +function formatWhen(iso) { + const then = new Date(iso); + const minutes = Math.round((Date.now() - then.getTime()) / 60000); + if (minutes < 1) return 'just now'; + if (minutes < 60) return `${minutes}m ago`; + if (minutes < 60 * 24) return `${Math.round(minutes / 60)}h ago`; + return then.toLocaleDateString(); +} + +function setBusy(busy) { + state.busy = busy; + el('connect').disabled = busy; + el('test-connection').disabled = busy; +} + +// ── Form → payload ─────────────────────────────────────────────────────── + +function readForm() { + const profile = selected(); + const payload = { + id: state.draft ? undefined : profile?.id, + name: dom.fields.name.value, + transport: state.transport, + url: dom.fields.url.value, + tls: { + mode: dom.fields.tlsMode.value, + fingerprint: dom.fields.tlsFingerprint.value, + caPath: dom.fields.tlsCa.value, + }, + ssh: { + host: dom.fields.sshHost.value, + port: dom.fields.sshPort.value, + username: dom.fields.sshUser.value, + authMethod: dom.fields.sshAuth.value, + privateKeyPath: dom.fields.sshKey.value, + remoteHost: dom.fields.remoteHost.value, + remotePort: dom.fields.remotePort.value, + localPort: dom.fields.localPort.value, + }, + }; + + // An empty secret box means "leave what is stored alone", not "clear it" — + // otherwise every save would wipe the keychain entry the user just made. + if (dom.fields.sshPassphrase.value) payload.ssh.passphrase = dom.fields.sshPassphrase.value; + if (dom.fields.sshPassword.value) payload.ssh.password = dom.fields.sshPassword.value; + + return payload; +} + +/** Persist the form and return the saved profile. */ +async function save() { + const saved = await api.profiles.save(readForm()); + state.draft = null; + state.selectedId = saved.id; + state.profiles = await api.profiles.list(); + renderList(); + return saved; +} + +function validate() { + if (state.transport === 'direct') { + if (!dom.fields.url.value.trim()) return 'Enter the DeepSQL server URL.'; + if (dom.fields.tlsMode.value === 'custom-ca' && !dom.fields.tlsCa.value.trim()) { + return 'Select the CA bundle to verify against.'; + } + return null; + } + if (!dom.fields.sshHost.value.trim()) return 'Enter the SSH host.'; + if (!dom.fields.sshUser.value.trim()) return 'Enter the SSH username.'; + if (dom.fields.sshAuth.value === 'key' && !dom.fields.sshKey.value.trim()) { + return 'Select the private key file to authenticate with.'; + } + return null; +} + +// ── Actions ────────────────────────────────────────────────────────────── + +function select(id) { + state.draft = null; + state.selectedId = id; + say(''); + renderList(); + renderEditor(); +} + +function newProfile(prefill = {}) { + state.draft = { + id: null, + name: prefill.name || 'DeepSQL VM', + transport: prefill.transport || 'direct', + url: prefill.url || '', + tls: { mode: 'system', fingerprint: '', caPath: '' }, + ssh: { + host: prefill.sshHost || '', + port: 22, + username: prefill.sshUser || 'ubuntu', + authMethod: 'key', + privateKeyPath: '', + remoteHost: '127.0.0.1', + remotePort: 3000, + localPort: 0, + hostKeyFingerprint: '', + hasStoredPassphrase: false, + hasStoredPassword: false, + }, + lastConnectedAt: null, + }; + state.selectedId = null; + say(''); + renderList(); + renderEditor(); + dom.fields.name.focus(); + dom.fields.name.select(); +} + +async function testConnection() { + const problem = validate(); + if (problem) { + say(problem, 'error'); + return; + } + setBusy(true); + setStatus('busy', 'Testing'); + say('Testing connection…', 'busy'); + try { + const profile = await save(); + const result = await api.profiles.test(profile.id, transientSecrets()); + if (result.ok) { + setStatus('idle', 'Not connected'); + say( + `DeepSQL responded in ${result.latencyMs} ms${ + result.hostKeyFingerprint ? ` · host key ${result.hostKeyFingerprint}` : '' + }.`, + 'ok', + ); + state.profiles = await api.profiles.list(); + renderEditor(); + } else { + setStatus('error', 'Failed'); + say(result.detail, 'error'); + } + } catch (err) { + setStatus('error', 'Failed'); + say(err.message, 'error'); + } finally { + setBusy(false); + } +} + +async function connect() { + const problem = validate(); + if (problem) { + say(problem, 'error'); + return; + } + setBusy(true); + setStatus('busy', 'Connecting'); + say('Connecting…', 'busy'); + try { + const profile = await save(); + const result = await api.connection.open(profile.id, transientSecrets()); + if (result.ok) { + state.active.add(profile.id); + setStatus('live', 'Connected'); + say('Connected. Opening DeepSQL…', 'ok'); + renderList(); + } else { + setStatus('error', 'Failed'); + say(result.detail, 'error'); + } + } catch (err) { + setStatus('error', 'Failed'); + say(err.message, 'error'); + } finally { + setBusy(false); + } +} + +/** + * Secrets typed right now are also passed straight to the transport, so a + * passphrase works on this attempt even when the OS keychain refused to store + * it (headless Linux) or the user is deliberately not saving it. + */ +function transientSecrets() { + return { + passphrase: dom.fields.sshPassphrase.value || undefined, + password: dom.fields.sshPassword.value || undefined, + }; +} + +async function deleteProfile() { + const profile = selected(); + if (!profile?.id) return; + await api.profiles.remove(profile.id); + state.active.delete(profile.id); + state.profiles = await api.profiles.list(); + state.selectedId = state.profiles[0]?.id || null; + state.draft = null; + renderList(); + renderEditor(); + say('Connection deleted.'); +} + +// ── Wiring ─────────────────────────────────────────────────────────────── + +function wire() { + el('new-connection').addEventListener('click', () => newProfile()); + el('empty-new').addEventListener('click', () => newProfile()); + el('delete-profile').addEventListener('click', deleteProfile); + el('test-connection').addEventListener('click', testConnection); + + dom.editor.addEventListener('submit', (event) => { + event.preventDefault(); + connect(); + }); + + for (const seg of document.querySelectorAll('.seg')) { + seg.addEventListener('click', () => { + state.transport = seg.dataset.transport; + syncVisibility(); + say(''); + }); + } + + dom.fields.tlsMode.addEventListener('change', syncVisibility); + dom.fields.sshAuth.addEventListener('change', syncVisibility); + + dom.fields.name.addEventListener('input', () => { + if (state.draft) state.draft.name = dom.fields.name.value; + renderList(); + }); + + el('browse-key').addEventListener('click', async () => { + const picked = await api.dialog.pickPrivateKey(); + if (picked) dom.fields.sshKey.value = picked; + }); + + el('browse-ca').addEventListener('click', async () => { + const picked = await api.dialog.pickCaBundle(); + if (picked) dom.fields.tlsCa.value = picked; + }); + + el('clear-host-key').addEventListener('click', async () => { + const profile = selected(); + if (!profile?.id) return; + await api.profiles.clearHostKey(profile.id); + state.profiles = await api.profiles.list(); + renderEditor(); + say('Pinned host key cleared. The next connection will pin whatever the VM presents.'); + }); + + api.onStatus((payload) => { + if (state.busy && payload.detail) say(payload.detail, 'busy'); + if (payload.status === 'ready') state.active.add(payload.profileId); + if (payload.status === 'closed') state.active.delete(payload.profileId); + renderList(); + }); + + api.onWorkspaceClosed(({ profileId }) => { + state.active.delete(profileId); + renderList(); + if (selected()?.id === profileId) setStatus('idle', 'Not connected'); + }); + + api.onDeepLink((payload) => { + newProfile(payload); + say('Pre-filled from a deepsql:// link. Review it, then connect.'); + }); +} + +async function renderMeta() { + const info = state.info; + dom.meta.replaceChildren(); + + const version = document.createElement('div'); + version.textContent = `DeepSQL Desktop ${info.version} · Electron ${info.electron}`; + + const keychain = document.createElement('div'); + keychain.textContent = info.keychainAvailable + ? 'Secrets stored in the OS keychain' + : 'No OS keychain — secrets kept for this session only'; + + const logs = document.createElement('button'); + logs.type = 'button'; + logs.textContent = 'Open log file'; + logs.addEventListener('click', () => api.app.openLog()); + + dom.meta.append(version, keychain, logs); +} + +async function boot() { + state.info = await api.app.info(); + state.profiles = await api.profiles.list(); + state.active = new Set(await api.connection.activeIds()); + state.selectedId = state.profiles[0]?.id || null; + + wire(); + await renderMeta(); + renderList(); + renderEditor(); + + if (state.profiles.length === 0) newProfile(); +} + +boot(); diff --git a/desktop/src/renderer/shared/theme.css b/desktop/src/renderer/shared/theme.css new file mode 100644 index 0000000..099a9d5 --- /dev/null +++ b/desktop/src/renderer/shared/theme.css @@ -0,0 +1,206 @@ +/* + * DeepSQL design tokens, lifted from src/index.css in the web app so the native + * shell and the embedded UI read as one product. Keep these in sync: if the web + * app's palette moves, this file moves with it. + * + * The webfont is loaded from Google Fonts exactly as the web app does. When the + * machine is offline the stack falls through to the system UI font, which is + * why the fallbacks are spelled out rather than left to `sans-serif`. + */ +@import url("https://fonts.googleapis.com/css2?family=Maven+Pro:wght@400;500;600;700;800&display=swap"); + +:root { + --font-family-sans: "Maven Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; + --font-family-mono: "JetBrains Mono", "SF Mono", "Fira Code", "IBM Plex Mono", Menlo, + Consolas, monospace; + + --color-white: #ffffff; + --color-canvas: #f5f5f7; + --color-light-2: #f3f4f6; + --color-light-3: #e5e7eb; + --color-light-4: #d1d5db; + --color-light-5: #9ca3af; + --color-light-6: #6b7280; + --color-light-8: #374151; + --color-text: #111827; + --color-text-secondary: #6b7280; + --color-ink: #0d0d0d; + --color-primary: #000000; + --color-primary-dark: #333333; + --color-border: #e5e7eb; + + --color-success: #16a34a; + --color-success-soft: #dcfce7; + --color-warning: #f59e0b; + --color-warning-soft: #fef3c7; + --color-danger: #ef4444; + --color-danger-dark: #dc2626; + --color-danger-soft: #fef2f2; + --color-danger-border: #fecaca; + --color-danger-text: #b91c1c; + + --radius-sm: 0.5rem; + --radius-md: 0.75rem; + --radius-lg: 1rem; + --radius-button: 9999px; + + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); + --shadow-card: 0 4px 24px rgba(0, 0, 0, 0.04); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* The UA rule for [hidden] is `display: none`, which any later `display: flex` + on the same element silently beats. Both renderers toggle visibility with the + hidden attribute, so it has to win outright. */ +[hidden] { + display: none !important; +} + +html, +body { + height: 100%; +} + +body { + margin: 0; + background: var(--color-canvas); + color: var(--color-text); + font-family: var(--font-family-sans); + font-size: 14px; + line-height: 1.6; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow: hidden; + user-select: none; + cursor: default; +} + +button { + font-family: inherit; + font-size: 14px; + line-height: 1.4; + border: none; + background: transparent; + color: var(--color-light-8); + border-radius: 8px; + padding: 6px 12px; + font-weight: 500; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + cursor: pointer; + letter-spacing: -0.01em; + transition: background 0.15s ease, color 0.15s ease, opacity 0.15s ease; +} + +button:hover:not(:disabled) { + background: var(--color-light-2); + color: var(--color-text); +} + +button:disabled { + cursor: not-allowed; + opacity: 0.45; +} + +button:focus-visible, +input:focus-visible, +select:focus-visible { + outline: 2px solid var(--color-light-4); + outline-offset: 1px; +} + +input, +select { + font-family: inherit; + font-size: 14px; + width: 100%; + padding: 9px 12px; + color: var(--color-text); + background: var(--color-white); + border: 1px solid var(--color-light-4); + border-radius: var(--radius-md); + transition: border-color 0.15s ease, box-shadow 0.15s ease; + user-select: text; +} + +input::placeholder { + color: var(--color-light-5); +} + +input:focus, +select:focus { + outline: none; + border-color: var(--color-light-6); + box-shadow: 0 0 0 3px rgba(209, 213, 219, 0.45); +} + +.btn-primary { + background: var(--color-primary); + color: var(--color-white); + border-radius: var(--radius-button); + padding: 10px 22px; + font-weight: 600; +} + +.btn-primary:hover:not(:disabled) { + background: var(--color-primary-dark); + color: var(--color-white); +} + +.btn-secondary { + background: var(--color-white); + border: 1px solid var(--color-light-4); + border-radius: var(--radius-button); + padding: 9px 18px; + color: var(--color-light-8); + font-weight: 500; +} + +.btn-secondary:hover:not(:disabled) { + background: var(--color-light-2); +} + +.btn-danger { + color: var(--color-danger-dark); +} + +.btn-danger:hover:not(:disabled) { + background: var(--color-danger-soft); + color: var(--color-danger-text); +} + +.mono { + font-family: var(--font-family-mono); + font-size: 12px; + letter-spacing: -0.01em; +} + +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-thumb { + background: var(--color-light-4); + border: 3px solid transparent; + background-clip: content-box; + border-radius: 999px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--color-light-5); + background-clip: content-box; +} + +::-webkit-scrollbar-track { + background: transparent; +} From b7037f11ae0c08b269da2947f872080e86895bf9 Mon Sep 17 00:00:00 2001 From: "K. Kaushik Reddy" Date: Sat, 8 Aug 2026 23:15:39 -0700 Subject: [PATCH 2/2] fix(desktop): allow loopback origins so tunnel connections pass CORS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Connecting to a VM through the SSH tunnel failed with "Request failed with status code 403" as soon as the user tried to log in. The tunnel serves the web app from http://127.0.0.1:, not the VM's hostname, and a self-host deployment that sets CORS_ALLOWED_ORIGINS to its public hostname replaces the built-in list rather than extending it. Spring treats any request carrying Origin as cross-origin (the same-origin short-circuit went away in 5.3), so the backend answered 403 with the plain-text body "Invalid CORS request". That body has no `message` field, so client.js's axios interceptor fell through to axios's own wording — an error naming neither CORS nor the origin. It hid well: Chromium omits Origin on same-origin GETs, so the health probe, the SPA and every read succeeded and the connection tested green. Only the first POST — the login — failed. - probe.js sends an Origin header, so the rejection is caught at connect time rather than at the user's first login, and transport.js reports it as `cors-rejected` naming the origin and the exact allowlist to set. - Loopback entries in the shipped defaults now carry a port wildcard, since the tunnel's local port is chosen at runtime. Legal only because SecurityConfig uses setAllowedOriginPatterns. - .env.example, docker-compose.yml and desktop/README.md spell out that CORS_ALLOWED_ORIGINS replaces the list, which is how the loopback entries go missing. - CLAUDE.md and config.js drop the "zero backend changes" claim: CORS is the one setting the thin client does require. - tunnel-selftest.js grows two checks (14/14) covering the Origin header and a 403 from an allowlist that omits the origin. Co-Authored-By: Claude Opus 5 --- .env.example | 13 ++++- CLAUDE.md | 24 ++++++-- .../resources/application-prod.properties | 7 ++- .../src/main/resources/application.properties | 18 +++++- desktop/README.md | 57 +++++++++++++++++-- desktop/scripts/tunnel-selftest.js | 33 +++++++++++ desktop/src/main/config.js | 9 ++- desktop/src/main/probe.js | 24 +++++++- desktop/src/main/transport.js | 21 ++++++- docker-compose.yml | 8 ++- 10 files changed, 192 insertions(+), 22 deletions(-) diff --git a/.env.example b/.env.example index bf83588..97d57fe 100644 --- a/.env.example +++ b/.env.example @@ -215,8 +215,17 @@ DEEPSQL_BACKEND_PORT=8080 DEEPSQL_POSTGRES_PORT=5432 DEEPSQL_VALKEY_PORT=6379 -# Browser origins allowed to call the backend -CORS_ALLOWED_ORIGINS=http://localhost:3000 +# Browser origins allowed to call the backend. +# +# This REPLACES the built-in list — it does not add to it. When you put your own +# hostname here, keep the loopback patterns too. The desktop client reaches a VM +# over an SSH tunnel and therefore serves the app from http://127.0.0.1:, +# with a port picked at runtime; if that origin is not allowed the app loads +# normally and then every login fails with a bare "403 Invalid CORS request". +# The `*` is a port wildcard (SecurityConfig uses setAllowedOriginPatterns). +# +# CORS_ALLOWED_ORIGINS=https://deepsql.example.com,http://127.0.0.1:*,http://localhost:* +CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:*,http://localhost:* # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # OPTIONAL — Email / SMTP diff --git a/CLAUDE.md b/CLAUDE.md index dffa41b..3db6c8f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -109,12 +109,28 @@ npm run selftest:tunnel # end-to-end SSH tunnel test (in-process SSH server) **It is a thin client and deliberately does not bundle the React frontend.** It navigates a `WebContentsView` at the real DeepSQL origin, so the UI is always the version the VM is running — no bundle/backend skew, and no second copy of 40+ -tabs to maintain. This works with **zero backend changes** because -`docker/nginx/default.conf` already serves the SPA, `/api` and `/agent-api` from -one origin: cookies, CORS and SSE behave exactly as in a browser. Do not -"improve" this by bundling `dist/` — that reintroduces CORS, `SameSite`, and +tabs to maintain. `docker/nginx/default.conf` already serves the SPA, `/api` and +`/agent-api` from one origin, so cookies and SSE behave exactly as in a browser. +Do not "improve" this by bundling `dist/` — that reintroduces `SameSite` and version-skew problems the current design does not have. +**It needs exactly one piece of backend configuration, and CORS is it.** The +"zero backend changes" claim that used to sit here was wrong, and cost a long +debugging session. Over a tunnel the origin is `http://127.0.0.1:`, +not the VM's hostname, so a deployment whose `CORS_ALLOWED_ORIGINS` names only +its public hostname rejects the desktop client. The failure is maximally +misleading: Chromium omits `Origin` on same-origin GETs, so the health probe, +the SPA and every read succeed, and the *first POST* — the login — comes back +`403` with the plain-text body `Invalid CORS request`. That body has no +`message` field, so `client.js`'s axios interceptor falls through to axios's own +wording and the user sees **"Request failed with status code 403"**, which names +neither CORS nor the origin. Fix: keep loopback patterns in the allowlist — +`CORS_ALLOWED_ORIGINS=https://your-host,http://127.0.0.1:*,http://localhost:*`. +Port wildcards work only because `SecurityConfig` uses +`setAllowedOriginPatterns`; `setAllowedOrigins` would reject `*` alongside +`allowCredentials(true)`. `probe.js` now sends an `Origin` header for exactly +this reason, so the rejection is caught at connect time and named. + **Two transports, one abstraction.** Both resolve to an *origin*, so nothing downstream of `desktop/src/main/transport.js` knows which is in use: diff --git a/backend/src/main/resources/application-prod.properties b/backend/src/main/resources/application-prod.properties index d4d056f..b6d8fac 100644 --- a/backend/src/main/resources/application-prod.properties +++ b/backend/src/main/resources/application-prod.properties @@ -57,8 +57,11 @@ app.base-url=${APP_BASE_URL:http://localhost:3000} # CORS Configuration # Override CORS_ALLOWED_ORIGINS with the origin(s) your frontend is -# actually served from. The default below covers local dev only. -cors.allowed.origins=${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost:3001} +# actually served from, and keep the loopback patterns: the desktop +# client's SSH tunnel serves the app from http://127.0.0.1:, +# so dropping them rejects every tunnel login with 403 "Invalid CORS +# request". See the longer note in application.properties. +cors.allowed.origins=${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost:3001,http://127.0.0.1:*,http://localhost:*} # File upload limits (slow query logs can be large) spring.servlet.multipart.max-file-size=2048MB diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 672453a..c3a55f7 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -81,10 +81,22 @@ db-scheduler.shutdown-max-wait=45m db-scheduler.immediate-execution-enabled=true # CORS Configuration -# Localhost only by default so `mvn spring-boot:run` + `npm run dev` works out of the box. +# Loopback only by default so `mvn spring-boot:run` + `npm run dev` works out of the box. # Any deployment serving a browser from another host must set CORS_ALLOWED_ORIGINS. -# Note: exact origins (no patterns) for reliability. -cors.allowed.origins=${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost:3001,http://localhost:3002,http://127.0.0.1:3000,http://127.0.0.1:3001,http://127.0.0.1:3002} +# +# The loopback entries carry a port wildcard because the desktop client's SSH tunnel +# serves the app from http://127.0.0.1:, and that port is chosen at runtime. +# Enumerating ports here is what made every tunnel connection fail with a bare +# "403 Invalid CORS request": Spring treats any request carrying Origin as cross-origin +# (the same-origin short-circuit went away in 5.3), so an unlisted loopback port is +# rejected. SecurityConfig uses setAllowedOriginPatterns, so `*` is legal in the port +# position and stays compatible with allowCredentials(true) — plain setAllowedOrigins +# would not be. +# +# IMPORTANT: overriding CORS_ALLOWED_ORIGINS replaces this list wholesale. A deployment +# that sets it to its public hostname alone drops the loopback entries and breaks the +# desktop client. Keep the loopback patterns alongside your hostname. +cors.allowed.origins=${CORS_ALLOWED_ORIGINS:http://localhost:3000,http://localhost:3001,http://localhost:3002,http://127.0.0.1:3000,http://127.0.0.1:3001,http://127.0.0.1:3002,http://127.0.0.1:*,http://localhost:*} # File upload limits (slow query logs can be large) spring.servlet.multipart.max-file-size=2048MB diff --git a/desktop/README.md b/desktop/README.md index 08f0b3e..8b0505f 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -28,10 +28,13 @@ knowing: - The UI is always the exact version the VM is running. There is no bundle/backend skew and no second copy of 40+ tabs to keep in step. -- Cookies, CORS and SSE behave exactly as in a browser, because the app is - served from one origin — `docker/nginx/default.conf` already fronts `/api` - and `/agent-api` behind the frontend container. No backend change is needed - to support the desktop client. +- Cookies and SSE behave exactly as in a browser, because the app is served + from one origin — `docker/nginx/default.conf` already fronts `/api` and + `/agent-api` behind the frontend container. +- **CORS is the one exception, and the one backend setting you must get right.** + Over a tunnel that origin is `http://127.0.0.1:`, so the VM's + `CORS_ALLOWED_ORIGINS` has to allow it. See + [CORS on the VM](#cors-on-the-vm-the-403-nobody-can-read). - Everything the client adds is what a browser tab cannot show: which VM you are on, how you are reaching it, and whether that path is healthy. @@ -129,6 +132,52 @@ anything publicly. `http://127.0.0.1:` is a secure context in Chromium, so the backend's `Secure` session cookies are still accepted over the tunnel. +### CORS on the VM (the 403 nobody can read) + +The tunnel gives the web app the origin `http://127.0.0.1:`, not your VM's +hostname. If `CORS_ALLOWED_ORIGINS` on the VM names only the hostname, the +backend rejects that origin — and it does so in the most confusing way +available: + +- Chromium omits `Origin` on same-origin **GET**s, so the health probe, the SPA + and every read work. The connection tests green. +- Chromium *does* send `Origin` on same-origin **POST/PUT/DELETE**, and Spring + treats any request carrying `Origin` as cross-origin (the same-origin + short-circuit was removed in Spring 5.3). So the first POST — the login — + returns `403` with the plain-text body `Invalid CORS request`. +- That body has no `message` field, so the web app's axios interceptor falls + back to axios's own wording: **"Request failed with status code 403"**, naming + neither CORS nor the origin. + +Fix it on the VM by keeping loopback patterns in the allowlist alongside your +hostname, then restarting the backend: + +```bash +# /home//deepsql-self-host/.env +CORS_ALLOWED_ORIGINS=https://deepsql.example.com,http://127.0.0.1:*,http://localhost:* + +docker compose up -d backend +``` + +The `*` is a **port** wildcard, which matters because the tunnel's local port is +chosen at runtime; enumerating ports means re-editing the VM whenever it +changes. It is legal only because `SecurityConfig` uses +`setAllowedOriginPatterns` — plain `setAllowedOrigins` rejects `*` in +combination with `allowCredentials(true)`. Note that `CORS_ALLOWED_ORIGINS` +*replaces* the built-in list rather than extending it, which is how the loopback +entries usually go missing. + +Verify without opening the app: + +```bash +curl -s -o /dev/null -w '%{http_code}\n' \ + -H "Origin: http://127.0.0.1:" http://127.0.0.1:/api/actuator/health +# 200 = allowed · 403 = still missing from CORS_ALLOWED_ORIGINS +``` + +Since the probe now sends an `Origin` header, the launcher catches this at +connect time and says so, instead of letting it surface as a failed login. + ## Security model - **Secrets** (key passphrases, SSH passwords) are encrypted with Electron diff --git a/desktop/scripts/tunnel-selftest.js b/desktop/scripts/tunnel-selftest.js index 4029935..0ea917e 100644 --- a/desktop/scripts/tunnel-selftest.js +++ b/desktop/scripts/tunnel-selftest.js @@ -40,8 +40,23 @@ app.whenReady().then(async () => { fs.writeFileSync(keyPath, privateKey, { mode: 0o600 }); // Stands in for the DeepSQL nginx inside the VM. + // + // It also emulates Spring's CORS check, because that is a real failure mode + // of the tunnel transport: the origin is http://127.0.0.1:, and + // a VM whose CORS_ALLOWED_ORIGINS lists only its hostname answers 403 with a + // plain-text body. Spring rejects on the presence of `Origin` alone — there + // is no same-origin exemption — so this mirrors that rule exactly. + let lastProbeOrigin = null; + let corsAllowedOrigins = null; // null = allow everything const upstream = http.createServer((req, res) => { if (req.url === '/api/actuator/health') { + const origin = req.headers.origin || null; + lastProbeOrigin = origin; + if (origin && corsAllowedOrigins && !corsAllowedOrigins.includes(origin)) { + res.writeHead(403, { 'Content-Type': 'text/plain' }); + res.end('Invalid CORS request'); + return; + } res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"status":"UP"}'); return; @@ -107,6 +122,24 @@ app.whenReady().then(async () => { forwardedTo, ); + // The probe must announce the origin the browser is about to use, or a CORS + // allowlist that omits it stays invisible until the user's first login POST. + check( + 'probe sends the browser origin so CORS is checked at connect time', + lastProbeOrigin === `http://127.0.0.1:${localPort}`, + lastProbeOrigin === null ? 'no Origin header sent' : lastProbeOrigin, + ); + + // Same tunnel, same healthy backend — only the allowlist changes. + corsAllowedOrigins = ['https://deepsql.example.com']; + const corsHealth = await probe(`http://127.0.0.1:${localPort}`, profile); + check( + 'an origin missing from CORS_ALLOWED_ORIGINS fails the probe', + !corsHealth.ok && corsHealth.status === 403, + `ok=${corsHealth.ok} status=${corsHealth.status}`, + ); + corsAllowedOrigins = null; + // The listener must never be reachable from anything but loopback. check( 'listener is bound to loopback only', diff --git a/desktop/src/main/config.js b/desktop/src/main/config.js index 30957bf..a347321 100644 --- a/desktop/src/main/config.js +++ b/desktop/src/main/config.js @@ -7,9 +7,14 @@ * It navigates a WebContentsView at the real DeepSQL origin (reached either * directly over TLS or through an SSH tunnel), so the UI a user sees is always * exactly the version their VM is running. There is no bundle/backend skew to - * manage, and cookies/CORS behave the same as they do in a browser because the - * app content is served from a single origin (the frontend nginx in + * manage, and cookies behave the same as they do in a browser because the app + * content is served from a single origin (the frontend nginx in * docker/nginx/default.conf already fronts /api and /agent-api). + * + * CORS is the one thing that does *not* come for free: over a tunnel that single + * origin is http://127.0.0.1:, which the VM's CORS_ALLOWED_ORIGINS + * has to allow. See the note in probe.js — the probe sends an Origin header so a + * missing entry is caught here rather than at the user's first login attempt. */ const path = require('node:path'); diff --git a/desktop/src/main/probe.js b/desktop/src/main/probe.js index 562f058..f047ca0 100644 --- a/desktop/src/main/probe.js +++ b/desktop/src/main/probe.js @@ -7,6 +7,21 @@ * proxies (docker/nginx/default.conf routes /api/ to the backend), so a 200 * here proves the whole chain — transport, nginx, backend — not just that a * TCP port answered. + * + * The probe deliberately sends an `Origin` header naming the origin the + * embedded browser is about to load. Spring treats *any* request carrying + * `Origin` as a CORS request (the same-origin short-circuit was dropped in + * Spring 5.3), so an origin missing from the backend's `CORS_ALLOWED_ORIGINS` + * is rejected with `403 Invalid CORS request` — and this probe sees it. + * + * Without the header the probe passes and the failure surfaces much later and + * much further away: Chromium omits `Origin` on same-origin GETs, so the SPA + * loads fine and only the first POST — the login itself — fails, as an opaque + * "Request failed with status code 403" (the body is plain text, so the web + * app's axios interceptor finds no `.message` to show). Over a tunnel this is + * near-guaranteed, because the origin is `http://127.0.0.1:` and + * no deployment lists that by hand. Same reasoning as verifyForwarding(): + * check the thing up front, where it can still be explained. */ const http = require('node:http'); @@ -47,7 +62,14 @@ function probe(origin, profile, { timeoutMs = DEFAULT_TIMEOUT_MS, path = HEALTH_ try { options = { method: 'GET', - headers: { Accept: 'application/json', 'User-Agent': 'DeepSQL-Desktop' }, + headers: { + Accept: 'application/json', + 'User-Agent': 'DeepSQL-Desktop', + // `url.origin` rather than the caller's string: it is normalised + // (default ports dropped, no trailing slash) exactly as a browser + // would send it, so the check matches what Chromium does next. + Origin: url.origin, + }, ...(isHttps ? tls.nodeTlsOptions(profile) : {}), }; } catch (err) { diff --git a/desktop/src/main/transport.js b/desktop/src/main/transport.js index 84f6e7e..9f05219 100644 --- a/desktop/src/main/transport.js +++ b/desktop/src/main/transport.js @@ -96,7 +96,10 @@ class Transport extends EventEmitter { const health = await probe(origin, profile); if (!health.ok) { if (tunnel) await tunnel.stop(); - throw new TunnelError('unreachable', explainProbeFailure(profile, health)); + throw new TunnelError( + health.status === 403 ? 'cors-rejected' : 'unreachable', + explainProbeFailure(profile, origin, health), + ); } // First successful TLS handshake in pinned/insecure mode establishes the pin. @@ -192,7 +195,21 @@ class Transport extends EventEmitter { * `Host: 127.0.0.1:`. Say so, because "HTTP 404" on its own sends people * looking at the backend. */ -function explainProbeFailure(profile, health) { +function explainProbeFailure(profile, origin, health) { + // 403 is its own diagnosis and applies to both transports: the probe sends an + // Origin header, so the one thing that rejects a *reachable, healthy* DeepSQL + // with 403 is its CORS allowlist. Checked before the tunnel branch below, + // which would otherwise blame the remote port for a backend that answered + // perfectly well. + if (health.status === 403) { + return ( + `DeepSQL is running and reachable, but its backend refused the origin ${origin} ` + + '(HTTP 403, "Invalid CORS request"). Add that origin to CORS_ALLOWED_ORIGINS on the ' + + 'VM and restart the backend. A port wildcard is the durable form, because the local ' + + 'port changes: `CORS_ALLOWED_ORIGINS=https://your-host,http://127.0.0.1:*,' + + 'http://localhost:*`. Left unfixed, DeepSQL would load but every login would fail.' + ); + } if (profile.transport !== 'tunnel' || !health.status) return health.detail; const { remoteHost, remotePort } = profile.ssh; return ( diff --git a/docker-compose.yml b/docker-compose.yml index cb33e5d..01f36a9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -83,8 +83,12 @@ services: ENCRYPTION_KEYS: ${ENCRYPTION_KEYS:-} ENCRYPTION_KEY_ID: ${ENCRYPTION_KEY_ID:-} - # CORS — allow the frontend service (and optional custom domain) - cors.allowed.origins: ${CORS_ALLOWED_ORIGINS:-http://localhost:3000} + # CORS — allow the frontend service (and optional custom domain). + # Keep the loopback patterns when you set CORS_ALLOWED_ORIGINS: this + # variable REPLACES the list, and the desktop client's SSH tunnel serves + # the app from http://127.0.0.1:. Dropping them makes every + # tunnel login fail with a bare 403 "Invalid CORS request". + cors.allowed.origins: ${CORS_ALLOWED_ORIGINS:-http://localhost:3000,http://127.0.0.1:*,http://localhost:*} # Dashboard generation + Slack/channels call Hermes server-side (AgentChatClient), # not via the browser /agent-api proxy. Point at the host webui; there is no