diff --git a/.augment/README.md b/.augment/README.md
deleted file mode 100644
index ab2956a..0000000
--- a/.augment/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# .augment
-
-Project AI rules live in the repo root: **CLAUDE.md**. Use it for workflow, branch flow, and critical patterns.
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
deleted file mode 100644
index 231d09c..0000000
--- a/.claude/settings.local.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "permissions": {
- "allow": [
- "Bash(tasklist:*)",
- "Bash(findstr:*)",
- "Bash(ipconfig:*)",
- "Bash(npm start)",
- "mcp__MCP_DOCKER__browser_navigate",
- "mcp__MCP_DOCKER__browser_take_screenshot",
- "Bash(curl:*)",
- "Bash(1 -H \"Icy-MetaData: 1\")",
- "Bash(start \"\" \"c:\\\\Users\\\\Username\\\\Documents\\\\github\\\\LANStreamer\\\\Start LANStreamer Server.bat\")",
- "Bash(timeout /t 5 /nobreak)",
- "Bash(node:*)",
- "Bash(cmd /c \"cd /d C:\\\\Users\\\\Username\\\\Documents\\\\github\\\\LANStreamer && dir package.json && dir node_modules >nul 2>&1 && echo node_modules exists || echo node_modules NOT found\")",
- "mcp__MCP_DOCKER__browser_network_requests",
- "Bash(cmd /c \"cd /d C:\\\\Users\\\\Username\\\\Documents\\\\github\\\\LANStreamer && Start~1~LAN~1.Server.bat 2>&1\")",
- "Bash(git branch:*)",
- "Bash(cmd /c \"node --version && echo Node.js OK\")",
- "Bash(cmd /c:*)",
- "Bash(git fetch:*)",
- "Bash(netstat:*)",
- "Bash(taskkill:*)",
- "Bash(powershell -Command \"Stop-Process -Id 57624 -Force\")",
- "mcp__MCP_DOCKER__fetch",
- "Bash(cmd.exe /c \"tasklist /FI \"\"IMAGENAME eq icecast.exe\"\"\")",
- "Bash(cmd.exe /c \"netstat -ano | findstr :8000\")",
- "Bash(cmd.exe /c \"ffmpeg -version\")",
- "Bash(git checkout:*)",
- "Bash(git log:*)",
- "Bash(for version in v1.2.0 v1.2.2 v1.2.3)",
- "Bash(do echo \"== $version ==\")",
- "Bash(done)",
- "Bash(dir:*)",
- "Bash(powershell \"Select-Object -Last 5\")",
- "Bash(npm update:*)",
- "Bash(if not exist \"C:\\\\Users\\\\Username\\\\.claude\\\\skills\" mkdir \"C:\\\\Users\\\\Username\\\\.claude\\\\skills\")",
- "Bash(powershell:*)",
- "Bash(more:*)",
- "Bash(type:*)",
- "Bash(del \"C:\\\\Users\\\\Username\\\\Documents\\\\github\\\\LANStreamer\\\\docs\\\\ICECAST_CONFIG_ARCHITECTURE.md\")",
- "Bash(npm test:*)",
- "Bash(gh run list:*)",
- "Bash(gh run view:*)",
- "Bash(xargs:*)",
- "Bash(cmd.exe /c \"netstat -ano | findstr :3001\")",
- "Bash(tail:*)",
- "Bash(timeout 5 ffmpeg:*)",
- "Bash(timeout 3 ffmpeg:*)",
- "Bash(git stash:*)",
- "Bash(git pull:*)",
- "Bash(git merge:*)",
- "Bash(gh pr create:*)",
- "Bash(gh pr view:*)",
- "Bash(gh pr edit:*)",
- "Bash(git rebase:*)"
- ]
- }
-}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2f5766e..7338566 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -29,5 +29,8 @@ jobs:
- name: Install dependencies
run: npm ci
+ - name: Integrity check (design tokens + UI rules)
+ run: node scripts/check-design-tokens.mjs
+
- name: Run tests
run: npm test
diff --git a/.github/workflows/enforce-prs.yml b/.github/workflows/enforce-prs.yml
new file mode 100644
index 0000000..c195299
--- /dev/null
+++ b/.github/workflows/enforce-prs.yml
@@ -0,0 +1,57 @@
+name: enforce-prs
+
+# Free-tier branch protection (adopted from the devops repo, 2026-10-28):
+# every commit that lands on main must (a) belong to a merged PR and (b)
+# have a green CI run for that exact commit. Direct pushes and red-CI
+# merges are auto-reverted (GITHUB_TOKEN pushes do not re-trigger
+# workflows, so the revert itself doesn't loop). dev stays open for the
+# documented local-merge workflow; only main (the release branch) is
+# protected. Replace with native branch protection if the repo upgrades
+# to GitHub Pro or goes public.
+
+on:
+ workflow_run:
+ workflows: ["CI"]
+ types: [completed]
+
+jobs:
+ verify-pr:
+ if: >
+ github.event.workflow_run.head_branch == 'main' &&
+ github.event.workflow_run.event == 'push'
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: read
+ steps:
+ - name: Require green CI and PR association for this commit
+ env:
+ GH_TOKEN: ${{ github.token }}
+ REPO: ${{ github.repository }}
+ SHA: ${{ github.event.workflow_run.head_sha }}
+ CONCLUSION: ${{ github.event.workflow_run.conclusion }}
+ run: |
+ if [ "$CONCLUSION" != "success" ]; then
+ echo "::error::CI concluded '$CONCLUSION' for $SHA on main. This commit will be reverted."
+ exit 78
+ fi
+ n=$(gh api "repos/$REPO/commits/$SHA/pulls" --jq 'length')
+ echo "associated PRs: $n"
+ if [ "$n" -eq 0 ]; then
+ echo "::error::Direct push to main is not allowed. Open a PR (CI must pass, then merge). This commit will be reverted."
+ exit 78
+ fi
+ - name: Revert the offending push
+ if: failure()
+ env:
+ GH_TOKEN: ${{ github.token }}
+ REPO: ${{ github.repository }}
+ SHA: ${{ github.event.workflow_run.head_sha }}
+ run: |
+ git config --global user.name "ci-guard"
+ git config --global user.email "ci-guard@users.noreply.github.com"
+ git clone "https://x-access-token:${GH_TOKEN}@github.com/${REPO}.git" repo
+ cd repo
+ git revert --no-edit "$SHA" || { echo "revert failed (merge conflict?) — MANUAL ACTION REQUIRED"; exit 1; }
+ git push origin main
+ echo "Reverted $SHA on main."
diff --git a/.gitignore b/.gitignore
index 263e93f..f01d5e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -123,6 +123,7 @@ dev-docs/
config/streams.json
config/device-config.json
config/contact-details.json
+config/security.json
config/web/
config/admin/
@@ -133,3 +134,15 @@ Desktop.ini
# Windows reserved name (can appear as accidental file)
nul
+/release/
+.claude/settings.local.json
+.claude-consult-prompt.md
+# Root config/ holds per-install runtime state — anchored so src/config/ (source
+# code) is never caught by this pattern (it silently blocked `git add` there).
+/config/
+/config/binary-probe.json
+/config/telemetry.json
+electron/telemetry-key.json
+
+# Bundled FFmpeg/Icecast binaries for the installer (fetched, never committed)
+/vendor/
diff --git a/CLAUDE.md b/CLAUDE.md
index 78bfcaf..9fbd895 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -4,8 +4,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Context
-**Project Type:** Node.js audio streaming server
-**Key Technologies:** FFmpeg, Icecast, Express.js, Socket.io
+**Project Type:** Electron desktop app (LAN audio streaming; Express server embedded in the Electron main process)
+**Key Technologies:** Electron, FFmpeg, Icecast, Express.js, PostHog (voluntary telemetry)
**Architecture:**
- `src/services/StreamingService.js` → Core FFmpeg process management
@@ -20,6 +20,24 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- **dev** is the integration branch. All changes land here (via merge or PR) before they can go to main.
- **Feature branches** are created from **main** (or **dev**) when starting new work. Pull from main into your feature branch if you need latest: `git fetch origin main && git merge origin/main` (or rebase).
- **Flow:** main → create `feature/xyz` → work → **merge feature into dev locally** → test → push dev → merge dev into main (release).
+- **main is now PR-protected (2026-10-28):** `enforce-prs.yml` auto-reverts any main commit that wasn't merged via a PR with green CI. Releases go dev → PR → main (pushing main directly gets reverted). dev stays open for the local-merge workflow above.
+
+### Pre-review gate for streaming features (enforced)
+
+Every PR that adds or changes streaming behavior (stream lifecycle,
+proxying, device capture, listener fanout, start-all, queueing) must
+answer the 7 hostile conditions in **docs/pressure-checklist.md**
+(uneven load, slow-not-down dependency, 10x data, machine dies mid-write,
+poor network, duplicate request, hostile traffic) in the PR description
+for the changed code path. Adopted from the devops practices DB.
+
+### Integrity linter (CI-enforced)
+
+`node scripts/check-design-tokens.mjs` fails CI on NEW violations of the
+UI rules below (hardcoded hex outside token sources, gray-* classes,
+native dialogs, runtime CDN refs). Existing debt is grandfathered in
+`scripts/design-token-baseline.json`; to accept new debt deliberately run
+`--update-baseline` and say why in the commit.
### Merge feature into dev locally (recommended)
@@ -54,6 +72,26 @@ Example: `git merge feature/start-all-and-unique-names`. After pushing dev, you
- FFmpeg exit codes are unsigned, require conversion to signed
- Example: 0xA7F00008 needs special handling
+## UI rules (enforced)
+
+- **Design tokens are the single source of truth**: `public/assets/css/tokens.css` (`--tok-*`, dark default + `[data-theme="light"]`). Tailwind maps them (`tailwind.config.js` → `bg-surface-1`, `text-muted`, `border-line`, `text-accent`, `rounded-pill`, `shadow-glow`…). **Never hardcode hex colors or dark-only Tailwind grays in new UI code** — use the semantic tokens so both themes work.
+- **Component showcase (dev-only) at `/showcase.html`**: every approved component variant, rendered from live tokens in both themes. New UI must match a pattern shown there — if it doesn't fit, extend the showcase first, then build. Check both themes on that page when touching tokens or `ui.css`.
+- **Shared components live in `public/assets/css/ui.css`**: `.btn-primary/secondary/ghost/danger`, `.play-btn`, `.copy-btn` (IconButton), `.channel-badge`, `.stream-row`, `.live-chip`, `.eq`, `.mq` (marquee), `.tok-label`, `.toast`/`.toast-stack` (via `LSToasts`), `.stream-error` (collapsed row error), `.ls-collapse` (remembered collapsibles via `LSCollapse`). New variants need a shared definition there first — no one-off button styles.
+- **Toasts must stack**: all transient notifications go through `LSToasts.show(message, type, {tag, linkUrl, linkText})` — it appends into `#toast-stack` so simultaneous toasts push down instead of overlapping; same-`tag` toasts replace each other. Never hand-roll `position:fixed` toasts.
+- **One icon family**: Material Symbols Rounded, locally served. Icon-only buttons must have `aria-label` + `title`. Replace decorative emoji used as UI icons; content emoji is fine.
+- **Sharing the listener page happens in ONE place** (header share card: open / copy / QR via `LSShare`). Never per-stream share buttons — we share the page, not individual mounts.
+- **Notifications**: transient confirmations via the page toast; stream failures stay visible near the stream; never `alert()`. Don't report success before the server confirms.
+- **Offline rule**: no runtime CDN dependencies — fonts/icons/styles all self-hosted (`build:css`, `vendor:fonts`).
+- After changing classes anywhere: run `npm run build:css`.
+- **No PWA on the listener page** (decision, 2026-10-28): installed shortcuts are bound to the origin they were made from, so a DHCP IP change kills every listener's shortcut. The page stays a plain bookmarkable URL; `streams.html` actively unregisters any leftover service worker. Don't re-add a manifest/SW without solving dynamic IPs first.
+
+## Telemetry (PostHog)
+
+- `src/services/TelemetryService.js` — opt-in only; **never** capture personal data, audio, stream names, or paths. Events: `app_start`, `stream_started` (format), `stream_stopped`, `stream_failed` (error category), `telemetry_enabled/disabled`. Distinct ID = anonymous install UUID from `config/telemetry.json`.
+- Enabled only when user consented (first-run Electron prompt; toggle in tray menu) **and** `POSTHOG_KEY` env is set (`POSTHOG_HOST` optional). No-op otherwise — keep it that way for any new events.
+- Skipped entirely under `NODE_ENV=test`. All calls are fire-and-forget with catch: telemetry must never break the app.
+- Docs: README "Telemetry & Privacy" (user-facing) + this section (dev-facing).
+
## Configuration
- `.env` - Environment variables (use `env.example` as template)
diff --git a/LANStreamer-redesign/README.md b/LANStreamer-redesign/README.md
new file mode 100644
index 0000000..86e5091
--- /dev/null
+++ b/LANStreamer-redesign/README.md
@@ -0,0 +1,36 @@
+# LANStreamer — UI/UX redesign
+
+Open `dashboard.html` or `listener.html` in any browser (no build step). Use the moon icon to switch light/dark; resize to see mobile.
+
+Files
+- `styles.css` — shared design tokens (light + dark) and components. Drop-in replacement for the current token sheet.
+- `app.js` — theme memory, stacked/tagged toasts, icons.
+- `dashboard.html` — admin dashboard (interactive mock: start/stop, filter, new-stream drawer, overflow menu, empty state).
+- `listener.html` — public listener page.
+
+## What changed and why
+
+Admin dashboard
+1. **Status strip at the top** — on-air count, listeners, Icecast status and "needs attention" are visible at a glance instead of buried in collapsed sidebar cards.
+2. **Security banner is actionable** — plain-language risk + a direct "Change password" button, in warning (not error) colour so it doesn't compete with real stream failures.
+3. **Live streams grouped first** — "On air" and "Ready" sections; no more hunting for the one live row among seven.
+4. **Full source names** — the old rows truncated the *start* of device names ("tput (VB-Audio…"). Names now truncate at the end with a tooltip.
+5. **Errors explain the fix** — the error row shows cause + "Change input" / "Retry" inline, instead of a collapsed "Audio Device Not Found" toggle.
+6. **Fewer icons per row** — one play/stop button + a "⋯" menu (copy link, edit, duplicate, delete). Delete no longer sits one click from Play. Up/down arrows replaced by a drag handle on hover.
+7. **Stop is visually distinct from Play** (red square vs neutral play), so the live row is unmistakable.
+8. **New stream as a side drawer** — input list shows which device is already in use and a live level meter; quality chosen by purpose (Speech / Standard / Music); optional auto-start.
+9. **Share card** — QR + copyable LAN address replaces the cramped "Listen to streams:" header pill.
+10. **Audio inputs always visible** — status (in use / idle / missing) per device instead of a "Component unavailable" collapsed panel.
+11. **Filters** (All / Live / Issues) and a friendlier empty state with a 3-step guide.
+
+Listener page
+1. **One big play button** with the current channel, live timer, listener count, waveform and volume.
+2. **Channel picker** for multi-room / multi-language events (designed for interpretation use).
+3. **Help line** for the most common "no sound" causes.
+4. **Mobile mini-player** stays pinned at the bottom after scrolling.
+5. Event artwork is themed from tokens instead of a fixed illustration; About/Contact are native, keyboard-accessible disclosures.
+
+Design system
+- Typography: Space Grotesk (UI) + JetBrains Mono (IDs, bitrates, timers).
+- Warning colour now separate from error; `--onair` reserved for the ON AIR badge.
+- Visible focus rings, `prefers-reduced-motion` respected, colour never the only status signal (text labels on every chip).
diff --git a/LANStreamer-redesign/app.js b/LANStreamer-redesign/app.js
new file mode 100644
index 0000000..a69aa4f
--- /dev/null
+++ b/LANStreamer-redesign/app.js
@@ -0,0 +1,26 @@
+// Shared: theme toggle (remembered), toasts, icons
+(function(){
+ const saved = localStorage.getItem('ls-theme');
+ const prefersDark = matchMedia('(prefers-color-scheme: dark)').matches;
+ document.documentElement.dataset.theme = saved || (prefersDark ? 'dark' : 'light');
+})();
+window.LS = {
+ toggleTheme(){
+ const t = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark';
+ document.documentElement.dataset.theme = t; localStorage.setItem('ls-theme', t);
+ },
+ toast(msg, tag){
+ let box = document.querySelector('.toasts');
+ if(!box){ box = document.createElement('div'); box.className='toasts'; box.setAttribute('aria-live','polite'); document.body.appendChild(box); }
+ if(tag){ const old = box.querySelector(`[data-tag="${tag}"]`); if(old) old.remove(); }
+ const t = document.createElement('div'); t.className='toast'; t.textContent=msg; if(tag) t.dataset.tag=tag;
+ box.appendChild(t); while(box.children.length>4) box.firstChild.remove();
+ setTimeout(()=>t.remove(), 3200);
+ }
+};
+const I = {
+ logo:' ',
+ play:' ',
+ stop:' ',
+ pause:' ',
+};
diff --git a/LANStreamer-redesign/dashboard.html b/LANStreamer-redesign/dashboard.html
new file mode 100644
index 0000000..12d13ed
--- /dev/null
+++ b/LANStreamer-redesign/dashboard.html
@@ -0,0 +1,275 @@
+
+
+
+
+LANStreamer — Admin dashboard
+
+
+
+
+
+
+
+
+
+
+
+
On air 1 / 7 streams
+
Listeners 23 peak 31
+
Icecast server Online:8000
+
Needs attention 1 stream · 1 setting
+
+
+
+
+
Default Icecast password in use. Anyone on your network could take over a stream.
+
Change password
+
+
+
+
+
+
+
+
+
+
No streams yet
+
Pick an audio input, name it, and go live — listeners on your Wi-Fi hear it instantly.
+
1 New stream2 Choose input3 Go live
+
Create first stream
+
Tip: route app audio with VB-Audio Cable or Dante Virtual Soundcard.
+
+
+
+
+
+
Share with listeners
+
+
+
+
Scan or open on any device on this network.
+
+
+
+
+
+
+
Event Edit
+
+
Title Sounds For A Beautiful Day
+
Feedback contact hello@example.com
+
Show on listener page
+
+
+
+
+
+
+ IN USE CABLE Output (VB-Audio Virtual Cable)
+ IDLE CABLE-A Output (VB-Audio Cable A)
+ IDLE Microphone (Realtek Audio)
+ MISSING OBS Virtual Camera (Audio)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LANStreamer-redesign/listener.html b/LANStreamer-redesign/listener.html
new file mode 100644
index 0000000..532a115
--- /dev/null
+++ b/LANStreamer-redesign/listener.html
@@ -0,0 +1,130 @@
+
+
+
+
+Sounds For A Beautiful Day — Live
+
+
+
+
+
+
+
+
+
LAN Streamer
+
+
ON AIR
+
+
+
+
+
+ Live now · on this network
+ Sounds For A Beautiful Day
+ Livestreaming you into a beautiful day!
+
+
+
+
+
+
+
+
LIVE13m 53s
+
Main Room English
+
192 kbps · 18 listening
+
+
+
+
+
+
+ Choose a channel
+ EN Main Room English Live · 18 listening
+ FR Side Room French Live · 5 listening
+ ES Spanish translation Starts soon
+
+
No sound? Make sure you're on the venue Wi-Fi and your phone isn't on silent. Keep this page open — audio continues with the screen locked.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LANStreamer-redesign/styles.css b/LANStreamer-redesign/styles.css
new file mode 100644
index 0000000..eee1b00
--- /dev/null
+++ b/LANStreamer-redesign/styles.css
@@ -0,0 +1,110 @@
+/* LANStreamer redesign — shared tokens + components */
+:root{
+ --bg:#F4F5F7; --surface-1:#FFFFFF; --surface-2:#EEF0F3; --inset:#E6E9EE;
+ --text-1:#0E1420; --text-2:#5A6475; --text-3:#8A93A3;
+ --line:rgba(14,20,32,.09); --line-strong:rgba(14,20,32,.16);
+ --accent:#0A84D6; --accent-soft:rgba(10,132,214,.10); --on-accent:#fff;
+ --live:#14A44D; --live-soft:rgba(20,164,77,.12);
+ --warn:#D98A04; --warn-soft:rgba(217,138,4,.12);
+ --danger:#D93025; --danger-soft:rgba(217,48,37,.10);
+ --onair:#E5372B;
+ --radius:14px; --radius-sm:9px;
+ --shadow:0 1px 2px rgba(14,20,32,.04),0 8px 24px -12px rgba(14,20,32,.12);
+ --font:"Space Grotesk",system-ui,sans-serif; --mono:"JetBrains Mono",ui-monospace,monospace;
+}
+[data-theme="dark"]{
+ --bg:#07090D; --surface-1:#0E1117; --surface-2:#141821; --inset:#0A0D12;
+ --text-1:#EEF1F6; --text-2:#97A0B0; --text-3:#636C7C;
+ --line:rgba(255,255,255,.07); --line-strong:rgba(255,255,255,.13);
+ --accent:#1AA6F5; --accent-soft:rgba(26,166,245,.13); --on-accent:#03121C;
+ --live:#2BD46A; --live-soft:rgba(43,212,106,.12);
+ --warn:#F5A524; --warn-soft:rgba(245,165,36,.13);
+ --danger:#F2555A; --danger-soft:rgba(242,85,90,.12);
+ --onair:#FF4A3D;
+ --shadow:0 1px 0 rgba(255,255,255,.03) inset,0 10px 30px -14px rgba(0,0,0,.7);
+}
+*{box-sizing:border-box;margin:0;padding:0}
+html,body{background:var(--bg);color:var(--text-1);font-family:var(--font);font-size:15px;line-height:1.45;-webkit-font-smoothing:antialiased}
+button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
+a{color:var(--accent);text-decoration:none}
+.mono{font-family:var(--mono);font-size:12px;letter-spacing:.01em}
+.muted{color:var(--text-2)} .faint{color:var(--text-3)}
+.wrap{max-width:1180px;margin:0 auto;padding:0 24px}
+:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:8px}
+
+/* Top bar */
+.topbar{position:sticky;top:0;z-index:20;background:color-mix(in oklab,var(--bg) 82%,transparent);backdrop-filter:blur(12px);border-bottom:1px solid var(--line)}
+.topbar .wrap{display:flex;align-items:center;gap:16px;height:64px}
+.brand{display:flex;align-items:center;gap:10px;font-weight:600;font-size:17px;letter-spacing:-.01em;min-width:0}
+.brand-mark{width:32px;height:32px;border-radius:9px;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;flex-shrink:0}
+.brand b{font-weight:700}
+.brand .sep{color:var(--text-3);font-weight:400;margin:0 2px}
+.brand .event{color:var(--text-2);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
+.spacer{flex:1}
+.iconbtn{width:36px;height:36px;border-radius:10px;display:grid;place-items:center;color:var(--text-2);position:relative;flex-shrink:0}
+.iconbtn:hover{background:var(--surface-2);color:var(--text-1)}
+.iconbtn .dot{position:absolute;top:7px;right:8px;width:7px;height:7px;border-radius:50%;background:var(--danger);box-shadow:0 0 0 2px var(--bg)}
+.svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
+
+/* Buttons */
+.btn{display:inline-flex;align-items:center;gap:8px;height:36px;padding:0 14px;border-radius:10px;font-weight:600;font-size:14px;white-space:nowrap;border:1px solid transparent;transition:background .15s,border-color .15s}
+.btn-primary{background:var(--accent);color:var(--on-accent)}
+.btn-primary:hover{filter:brightness(1.08)}
+.btn-secondary{background:var(--surface-1);border-color:var(--line-strong)}
+.btn-secondary:hover{background:var(--surface-2)}
+.btn-ghost{color:var(--text-2)} .btn-ghost:hover{background:var(--surface-2);color:var(--text-1)}
+.btn-danger{color:var(--danger);border-color:color-mix(in oklab,var(--danger) 35%,transparent)}
+.btn-danger:hover{background:var(--danger-soft)}
+.btn:disabled{opacity:.45;cursor:not-allowed}
+.btn-sm{height:30px;padding:0 10px;font-size:13px;border-radius:8px}
+
+/* Chips */
+.chip{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:999px;font-size:12px;font-weight:600;letter-spacing:.02em;white-space:nowrap}
+.chip .pip{width:6px;height:6px;border-radius:50%;background:currentColor}
+.chip-live{background:var(--live-soft);color:var(--live)}
+.chip-live .pip{animation:pulse 1.6s infinite}
+.chip-off{background:var(--surface-2);color:var(--text-2)}
+.chip-err{background:var(--danger-soft);color:var(--danger)}
+.chip-warn{background:var(--warn-soft);color:var(--warn)}
+.chip-accent{background:var(--accent-soft);color:var(--accent)}
+@keyframes pulse{0%{box-shadow:0 0 0 0 color-mix(in oklab,currentColor 60%,transparent)}70%{box-shadow:0 0 0 6px transparent}100%{box-shadow:0 0 0 0 transparent}}
+
+/* Cards */
+.card{background:var(--surface-1);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}
+.card-h{display:flex;align-items:center;gap:10px;padding:16px 18px;border-bottom:1px solid var(--line)}
+.card-h h2,.card-h h3{font-size:15px;font-weight:600;letter-spacing:-.005em}
+.card-b{padding:16px 18px}
+.eyebrow{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}
+
+/* Equalizer */
+.eq{display:inline-flex;align-items:flex-end;gap:2px;height:12px}
+.eq i{width:3px;background:currentColor;border-radius:1px;animation:eq 1s ease-in-out infinite}
+.eq i:nth-child(1){height:40%;animation-delay:-.2s}.eq i:nth-child(2){height:100%;animation-delay:-.5s}.eq i:nth-child(3){height:65%;animation-delay:-.1s}.eq i:nth-child(4){height:85%;animation-delay:-.7s}
+@keyframes eq{50%{transform:scaleY(.35)}}
+.eq i{transform-origin:bottom}
+
+/* Toggle */
+.switch{width:38px;height:22px;border-radius:999px;background:var(--inset);border:1px solid var(--line-strong);position:relative;transition:.2s;flex-shrink:0}
+.switch::after{content:"";position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:var(--surface-1);box-shadow:0 1px 2px rgba(0,0,0,.25);transition:.2s}
+.switch[aria-checked="true"]{background:var(--accent);border-color:var(--accent)}
+.switch[aria-checked="true"]::after{left:18px}
+
+/* Inputs */
+.field{display:flex;flex-direction:column;gap:6px}
+.field label{font-size:13px;font-weight:600}
+.field .hint{font-size:12px;color:var(--text-3)}
+.input,.select{height:40px;padding:0 12px;border-radius:10px;background:var(--inset);border:1px solid var(--line-strong);color:var(--text-1);font:inherit;font-size:14px;width:100%}
+.input:focus,.select:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
+
+/* Toast */
+.toasts{position:fixed;right:20px;bottom:20px;display:flex;flex-direction:column;gap:8px;z-index:60}
+.toast{display:flex;align-items:center;gap:10px;min-width:260px;max-width:360px;padding:12px 14px;border-radius:12px;background:var(--text-1);color:var(--bg);font-size:14px;box-shadow:0 12px 30px -10px rgba(0,0,0,.4);animation:tin .25s ease}
+@keyframes tin{from{transform:translateY(8px);opacity:0}}
+
+/* Footer */
+.foot{border-top:1px solid var(--line);margin-top:48px}
+.foot .wrap{display:flex;flex-wrap:wrap;gap:12px 20px;align-items:center;padding:20px 24px;font-size:13px;color:var(--text-3)}
+.foot a{color:var(--text-2)} .foot a:hover{color:var(--accent)}
+
+@media (max-width:720px){.wrap{padding:0 16px}.hide-sm{display:none!important}}
+@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
diff --git a/README.md b/README.md
index 0a49eb8..edf6bd6 100644
--- a/README.md
+++ b/README.md
@@ -1,162 +1,156 @@
# LANStreamer
-A comprehensive solution that turns a standard PC into a multi-channel audio streaming server for local area networks (LAN). This project provides a **web-based application** that orchestrates **FFmpeg** and **Icecast** to deliver local, live, low-latency audio broadcasts for events like language interpretation, meetings, or conferences.
+**LAN audio streaming for language interpretation, meetings, and events.** LANStreamer is a desktop app that turns an ordinary PC into a multi-channel audio streaming server for your local network (LAN) — it orchestrates **FFmpeg** and **Icecast** behind the scenes, so a whole room can listen to live, low-latency audio on their phones.
-## 📋 Documentation
-
-| Documentation | Description |
-|--------------|-------------|
-| **Quick Start** | This README - get up and running quickly |
-| **[Startup sequence](docs/STARTUP-SEQUENCE.md)** | Step-by-step process order for `npm run dev`; troubleshoot each step |
-| **[Troubleshooting](docs/TROUBLESHOOTING.md)** | Common issues: network, firewall, playback problems |
-| **[System Architecture](docs/LANSTREAMER_SYSTEM_ARCHITECTURE.md)** | ⭐ Complete technical documentation - all services, flows, and architecture |
-| [Installation Guides](docs/guides/README.md) | FFmpeg, Icecast setup guides |
-| [Network Setup](docs/NETWORK-SETUP.md) | Static IP configuration for events |
-| [Developer Guide](CLAUDE.md) | Architecture and contribution guide |
+> **Status: v2.0.0 is released** — download the installer or standalone build from [GitHub Releases](https://github.com/jerryagenyi/LANStreamer/releases) (both bundle FFmpeg + Icecast; nothing to pre-install). Running from source still works: `npm run electron:dev`, or the server-only `Start LANStreamer Server.bat`. Release process and pre-ship checks: [docs/GO-LIVE-CHECKLIST.md](docs/GO-LIVE-CHECKLIST.md).
---
-## 🚀 Quick Start
+## 🎯 What is LANStreamer?
+
+Think "wireless interpretation booth": the interpreter's PC captures audio (microphone, audio interface, or virtual audio cable) and broadcasts it over Wi-Fi. Anyone on the same network opens a link in their browser and listens — nothing to install.
+
+### Interfaces
+
+| Interface | Purpose | Access |
+|-----------|---------|--------|
+| **Admin Dashboard** | Control center for managing streams | `http://localhost:3001/dashboard` on the operator PC (login: `admin` / `lanstreamer123` by default) |
+| **Listener Interface** | User-friendly page for browsing and playing streams | `http://YOUR-PC-IP:3001/streams` (public, no login) |
+
+### Use Cases
+
+- **Language Interpretation**: Multiple language channels for conferences
+- **Meeting Audio**: Professional audio distribution for events
+- **Training Sessions**: Audio streaming for educational content
+- **Local Broadcasting**: Any situation requiring reliable, low-latency audio distribution
-### For Non-Technical Users
+---
-**Step 1: Install Prerequisites**
-- **Node.js**: Download from https://nodejs.org/ (choose "LTS" version)
-- **FFmpeg & Icecast**: See [Installation Guides](docs/guides/README.md)
+## 🚀 Quick Start (Desktop App)
-**Step 2: Download & Extract**
-1. Go to https://github.com/jerryagenyi/LANStreamer
-2. Click **"Code"** → **"Download ZIP"**
-3. Extract the ZIP file and open the `LANStreamer` folder
+**Step 1: Launch LANStreamer**
+Start the LANStreamer app on the operator PC. It starts the streaming server and opens the dashboard window automatically — no terminal windows to babysit. Closing the window only hides it to the tray: streams keep running for your listeners. To stop for real, use the tray icon → **Stop All & Quit**.
-**Step 3: One-Click Start**
-1. Double-click `Start LANStreamer Server.bat`
-2. Wait for dependencies to install and the server to start
-3. Note the URLs shown in the terminal
+> No app package? You can run the same server from a source/ZIP copy: double-click `Start LANStreamer Server.bat` (requires [Node.js](https://nodejs.org/) LTS, plus FFmpeg & Icecast — see the [Installation Guides](docs/guides/README.md)). Building the desktop package from source is covered in the [Developer Guide](docs/README-DEVELOPERS.md).
-**Step 4: Access Your Streaming Server**
-- **Admin Dashboard**: `http://YOUR-IP:3001` (login required)
-- **Listener Page**: `http://YOUR-IP:3001/streams` (public access)
+**Step 2: Sign In**
+The dashboard asks you to sign in when it opens.
-**Default Admin Credentials** (change these immediately in `.env`):
- **Username**: `admin`
- **Password**: `lanstreamer123`
-### For Technical Users
+Change these before your event — see [Security Setup](#-security-setup--admin-login) below.
-```bash
-# Clone and install
-git clone https://github.com/jerryagenyi/LANStreamer.git
-cd LANStreamer
-npm install
+**Step 3: Create a Stream**
+Click **Add stream**, pick an audio source (your microphone, audio interface, or virtual audio cable), choose a quality, and click **Go live**. Repeat for more channels (e.g. one per language). You can also use **Start All / Stop All**.
-# Start the server
-npm start
-```
+**Step 4: Share with Listeners**
+The dashboard's **Share with listeners** card shows the listener link (e.g. `http://192.168.x.x:3001/streams`). Copy it, or tap the QR icon and let people scan it. Share it once — by chat, email, projector slide, or QR on paper.
-Then visit `http://localhost:3001` for the admin dashboard.
+---
-> **Need more detail?** See [System Architecture](docs/LANSTREAMER_SYSTEM_ARCHITECTURE.md) or [Installation Guides](docs/guides/README.md)
+## 🎧 For Listeners
+
+1. Join the **same Wi-Fi/network** as the operator PC
+2. Open the shared link (or scan the QR code) — no app, no account, no login
+3. Tap the stream they want and press play
+
+The listener page is forgiving: it **auto-resumes** a stream that drops and comes back on air (unless they paused it themselves), and on reload it remembers the stream they played last.
---
-## 🎯 What is LANStreamer?
+## 🔐 Security Setup — Admin Login
-LANStreamer creates a complete audio streaming ecosystem with two main interfaces and three core components:
+**Default admin credentials:**
-### Interfaces
+| Setting | Value |
+|---------|-------|
+| Username | `admin` |
+| Password | `lanstreamer123` |
-| Interface | Purpose | Access |
-|-----------|---------|--------|
-| **Admin Dashboard** | Control center for managing streams | `http://localhost:3001/` (auth required) |
-| **Listener Interface** | User-friendly page for browsing and playing streams | `http://localhost:3001/streams` (public) |
+Sign in at `http://localhost:3001/dashboard` (or the Electron app window) — the login appears automatically when the dashboard is opened. The **listener page (`/streams`) has no login**; phones on the LAN just open the shared link.
-### Core Components
+**First run:** while the default credentials are active, the dashboard shows a banner stating them and how to change them — it disappears permanently once you set your own.
-1. **Audio Input** - Any detected audio device (microphone, audio interface, virtual audio cable)
-2. **FFmpeg** - Reads audio channels, encodes, and pushes to streaming server
-3. **Icecast** - Open-source streaming server that broadcasts to network clients
+**Forgot your password?** On the operator PC, delete the admin login file and restart LANStreamer — the default login above returns, and you can set a new one from the dashboard (Admin account). Installed app: `%APPDATA%\LANStreamer\security.json` · running from source: `config\security.json`. (The login page carries this same hint — it only opens on the operator's PC, so the path is safe to show there.)
-### Use Cases
+Admin access has two layers:
-- **Language Interpretation**: Multiple language channels for conferences
-- **Meeting Audio**: Professional audio distribution for events
-- **Training Sessions**: Audio streaming for educational content
-- **Local Broadcasting**: Any situation requiring reliable, low-latency audio distribution
+1. **Login (username + password)** — every admin API call requires a session token from signing in.
+2. **Localhost lock** — the dashboard and admin APIs refuse connections from other machines, so even someone on your LAN with the password cannot reach admin.
----
+To change the defaults, use the in-app settings: dashboard → sidebar → **Admin account** card → enter the current password and a new username/password → **Update login**. It applies immediately (no restart), signs out every other session, and is stored in the app's data folder — this works in the packaged desktop app, where there is no `.env` to edit.
-## 📁 Project Structure
+Running from source, `.env` also works — copy `env.example` to `.env`, then edit:
+```env
+ADMIN_USERNAME=your-new-username
+ADMIN_PASSWORD=your-strong-password
+JWT_SECRET=your-jwt-secret
+SESSION_SECRET=your-session-secret
```
-LANStreamer/
-├── Start LANStreamer Server.bat # Windows startup (double-click to start)
-├── Update LANStreamer.bat # Update script
-├── src/ # Backend (Node.js/Express)
-├── public/ # Frontend (web interface)
-├── config/ # Runtime config (auto-generated)
-├── docs/ # Documentation
-└── manual-setup/ # Hardware-specific guides
-```
-> **For developers:** See [CLAUDE.md](CLAUDE.md) for detailed architecture and code structure.
+Restart LANStreamer afterwards. (The in-app change takes precedence over `.env` values. Logins stay valid for 7 days, or set `JWT_EXPIRES_IN` to change that.)
+
+**Icecast (the streaming server LANStreamer drives) is hardened automatically when bundled.** The bundled Icecast binds to `127.0.0.1` only — listeners receive audio through LANStreamer's own play proxy on port 3001, so nothing about Icecast is ever exposed to your network — and its passwords are randomly generated per install (the app reads them itself; nobody ever types them). Someone who knows LANStreamer's defaults cannot reach or control it.
+
+Using your **own Icecast install** instead of the bundled one? That install is on your network as you configured it: if it still has Icecast's stock default passwords, the dashboard shows a security warning until you change them (edit `icecast.xml` in the install folder, e.g. `C:\Program Files (x86)\Icecast\icecast.xml` — the `` block — then restart LANStreamer).
---
## ⚙️ System Requirements
-- **Operating System**: Windows 10/11 (macOS/Linux supported)
-- **Node.js**: Version 18 or higher ([Download](https://nodejs.org/))
-- **FFmpeg**: Audio/video processing toolkit ([Download](https://ffmpeg.org/))
-- **Icecast**: Streaming media server ([Download](https://icecast.org/))
-- **Audio Input**: Any audio device (built-in mic, USB mic, audio interface, etc.)
+**Minimum (operator PC)**
+- Windows 10/11 64-bit (macOS/Linux supported from source)
+- 4 GB RAM, dual-core CPU — encoding one stream uses ~2–5% of a modern CPU
+- Any audio input (built-in mic, USB, or virtual audio cable)
+- FFmpeg + Icecast — **bundled with the desktop installer** (in preparation). Running from source/CLI? Install them separately (see [guides](docs/guides/README.md))
+
+**Listeners:** any phone/PC with a browser and WiFi — nothing to install. ~20–25 listeners per consumer WiFi access point for stable audio; larger events should add access points.
+
+**Recommended:** 8 GB RAM for 4+ simultaneous streams, wired Ethernet from the operator PC to the router, 5 GHz WiFi for listeners (see [Latency guide](docs/LATENCY.md)).
---
-## 🔐 Security Setup
+## 🛠️ Troubleshooting
+
+**Common Issues:**
-**⚠️ CRITICAL: Change Default Credentials Immediately!**
+| Problem | Quick Fix |
+|---------|-----------|
+| Stream won't start | Make sure the audio device isn't already in use by another app; rescan devices in the dashboard |
+| Listeners can't connect | Check everyone is on the **same Wi-Fi/network** as the operator PC, and the link uses the PC's LAN IP (not `localhost`). Also see [Firewall Issues](docs/TROUBLESHOOTING.md#firewall-issues) |
+| "This site can't be reached" | Likely subnet mismatch — see [Network Troubleshooting](docs/TROUBLESHOOTING.md#network-connectivity-issues) |
+| "Port 3001 already in use" | A leftover server instance is running — close its terminal window (or quit the app from the tray), or end `node.exe` in Task Manager, then relaunch. The dashboard's stop buttons end streams and Icecast, but no button can stop the server itself |
+| "No audio devices detected" | Ensure device is connected and not in use by another app |
+| "Stream format not supported" | See [Stream Playback Issues](docs/TROUBLESHOOTING.md#stream-playback-issues) |
+| Link/QR stopped working after moving networks | The share card always shows the PC's **current** network address — re-share the link/QR after the network changes; old links point at the old address |
+| Audio reaches listeners ~1–1.5 s after the room | Normal — the low-latency player holds a small buffer that also absorbs Icecast's ½-second delivery rhythm; how it works and how to tune it: [docs/LATENCY.md](docs/LATENCY.md) |
-1. Copy `env.example` to `.env`
-2. Edit `.env` and change:
- - `ADMIN_USERNAME=your-new-username`
- - `ADMIN_PASSWORD=your-strong-password`
- - `JWT_SECRET=your-jwt-secret`
- - `SESSION_SECRET=your-session-secret`
-3. Restart LANStreamer
+> **📖 In-app guide:** LANStreamer ships with a built-in troubleshooting page at `http://localhost:3001/docs` — open it from any browser on the operator PC. For the full guide see [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) (subnet issues, firewall configuration, network diagnostics).
---
## 🔄 Updating
-**For ZIP Users:**
-```bash
-# Double-click this file in your installation folder
-Update LANStreamer.bat
-```
+**Packaged installs (once released):** download the new installer from [GitHub Releases](https://github.com/jerryagenyi/LANStreamer/releases) and run it — your stream configuration is kept.
-**For Git Users:**
-```bash
-git pull origin main
-npm install # If dependencies changed
-```
+**ZIP/source installs:** double-click `Update LANStreamer.bat` in your installation folder.
---
-## 🛠️ Troubleshooting
+## 📊 Telemetry & Privacy
-**Common Issues:**
+LANStreamer is **free and open source — no one makes money from it, and no one should** (MIT license).
-| Problem | Quick Fix |
-|---------|-----------|
-| "npm not found" | Install Node.js from [nodejs.org](https://nodejs.org/) |
-| "Port 3001 already in use" | Close other apps using port 3001, or change `PORT` in `.env` |
-| "This site can't be reached" | Check [Network Troubleshooting](docs/TROUBLESHOOTING.md#network-connectivity-issues) - likely subnet mismatch |
-| "Connection refused" | Check [Firewall Setup](docs/TROUBLESHOOTING.md#firewall-issues) |
-| "No audio devices detected" | Ensure device is connected and not in use by another app |
-| "Stream format not supported" | See [Stream Playback Issues](docs/TROUBLESHOOTING.md#stream-playback-issues) |
+**Telemetry is ON by default (opt-out).** **What is collected:** anonymous events — app start, stream started/stopped/failed (with the error *category* only), app version, OS, and a random install ID. Every event also carries a fixed `app: lanstreamer` tag (the maintainer's PostHog project is shared across apps; the tag separates this app's events). **Never collected:** audio, stream names, contact details, file paths, IPs, or any personal data.
+
+**Listener failure reports:** when playback fails on a listener's device (audio error, buffer stall, the stream going off-air mid-listen, or the page failing to load), the listener page reports it to the *operator's own server*, which relays it to PostHog **only while the operator's telemetry is on** — carrying the stream label (e.g. "S1"), the media error code, and the browser platform. Listener devices never talk to PostHog directly and never hold any key; with telemetry off, the reports are dropped at the server.
-> **📖 Full Troubleshooting Guide:** See [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md) for detailed solutions including subnet issues, firewall configuration, and network diagnostics.
+- **First run** shows a plain notice that statistics are on, what they contain, and a one-click **Turn it off**.
+- **Change it anytime**: dashboard → sidebar → **Admin account** → *Anonymous usage statistics* switch, or tray icon → **Telemetry → On/Off**.
+- Events go to the maintainer's PostHog over the internet, queued and flushed in the background — nothing is sent while telemetry is off, and a fully offline LAN works either way.
+- Maintainers packaging a distributed build: run `node scripts/prepare-telemetry-key.mjs` before building — it bundles the PostHog key into the app (gitignored) so other operators' installs report too (each with their own off switch).
---
@@ -164,24 +158,19 @@ npm install # If dependencies changed
| Document | Description |
|----------|-------------|
-| **[Startup sequence](docs/STARTUP-SEQUENCE.md)** | Process order for `npm run dev`; troubleshoot step-by-step |
+| [In-app Guide](http://localhost:3001/docs) | Troubleshooting & guide page built into the app |
| **[Troubleshooting Guide](docs/TROUBLESHOOTING.md)** | Common issues and solutions (subnet, firewall, playback) |
-| [Network Setup](docs/NETWORK-SETUP.md) | Static IP configuration for live events |
| [Installation Guides](docs/guides/README.md) | FFmpeg and Icecast setup guides |
-| [Comprehensive Docs](docs/LANStreamer-Documentation.md) | Complete technical documentation |
-| [Developer Guide](CLAUDE.md) | Architecture and development workflow |
+| [Network Setup](docs/NETWORK-SETUP.md) | Static IP configuration for live events |
+| [Latency Guide](docs/LATENCY.md) | Getting the lowest latency for listeners |
| [Manual Setup](manual-setup/README.md) | Hardware-specific configuration guides |
| [Changelog](docs/CHANGELOG.md) | Version history and release notes |
---
-## 🤝 Contributing
-
-We welcome contributions! See [CLAUDE.md](CLAUDE.md) for the development workflow and architecture guide.
-
-**Branch workflow:** We never add to `main` directly. Pull from `main` when starting work; do work on a feature branch; merge into `dev` first; only then does change go to `main`. See [CLAUDE.md](CLAUDE.md) for the full flow.
+## 🧑💻 For Developers
-For bug reports, include your OS, Node.js version, and steps to reproduce.
+Building from source, running the test suite, architecture notes, and the contribution workflow (branch model, CI, UI rules, telemetry internals) all live in the **[Developer Guide](docs/README-DEVELOPERS.md)**. Preparing a release? Follow **[docs/GO-LIVE-CHECKLIST.md](docs/GO-LIVE-CHECKLIST.md)** (test matrix, packaging, versioning, GitHub release notes). See also [CLAUDE.md](CLAUDE.md) for enforced code patterns.
---
@@ -193,9 +182,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
## 🆘 Support
-1. Check the [Troubleshooting Guide](docs/TROUBLESHOOTING.md) first
-2. Review the [Installation Guides](docs/guides/README.md)
-3. See [Comprehensive Documentation](docs/LANStreamer-Documentation.md) for advanced topics
+1. Check the in-app guide at `http://localhost:3001/docs`
+2. See the [Troubleshooting Guide](docs/TROUBLESHOOTING.md)
+3. Review the [Installation Guides](docs/guides/README.md)
4. Create an issue on GitHub with detailed information
---
diff --git a/TODO.md b/TODO.md
index 13fa6e5..6f7c367 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,66 +1,49 @@
# LANStreamer – TODO
-Context: [CLAUDE.md](CLAUDE.md), [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md). Delete when done.
+Context: [CLAUDE.md](CLAUDE.md), [docs/APP-FLOW.md](docs/APP-FLOW.md), [docs/TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md). Delete items when done.
---
## To do (priority order)
-- [ ] **Explore: Listener song requests** — Extend LANStreamer so anyone on the network (mobile or PC) can request to play a song from their device; admin grants the request and the song is listed on the listener page for others to hear. Support multiple user requests.
+- [x] **Latency management — SHIPPED (2026-10-30)** — MSE listener player (~0.5 s buffered-ahead vs ~2.3 s browser default), FFmpeg low-delay flags, proxy no-Nagle/flushHeaders, 16 KB icecast burst. Measured: `scripts/verify-latency.mjs`. Remaining nice-to-have: "latency tips" link on the dashboard pointing at the operator-side guidance (5 GHz, dedicated AP, QoS, wired operator); sub-second would need a WebSocket/WebRTC + Opus transport rewrite (deferred — see docs/LATENCY.md).
-- [ ] **Centralize notifications/alerts** — Control all notifications, alerts, and toasts from a single place so one change impacts everywhere (e.g. styling, z-index, behaviour). To be done on branch `fix/error-handling-refactor` or a new dedicated branch (e.g. `refactor/centralize-notifications`).
+- [ ] **Minimum PC specs + cross-OS test story** — README section: minimum requirements (x64, 4 GB RAM, Node 18+ for source runs, FFmpeg, Icecast; packaged app drops the Node requirement). Cross-OS testing: GitHub Actions windows/macos/ubuntu matrix runs the suite + `electron:smoke` online (Phase 4); locally, Playwright covers the web pages on all three OSes; no credible downloadable "test on every PC" tool exists beyond VMs + the CI matrix.
-- [ ] **Centralised theming (light/dark, themes)** — UI-UX v2 was implemented with many styles inline in `index.html` and `streams.html` (duplicated variables, hardcoded colours). Refactor to a single theme layer (e.g. shared CSS or design tokens) so themes and light/dark mode can be added without touching every component. Prefer one source of truth for colours, shadows, and glass tokens.
+- [ ] **UI redesign — dashboard deep pass** — Restyle remaining dashboard sections (Icecast panel, event/contact panels, header) to the broadcast language on tokens; a11y sweep (aria, focus rings, 44px targets).
-- [x] **Lock admin to localhost** — Admin UI only on localhost; listeners use LAN IP. Implemented: `requireLocalhostAdmin` middleware; listener page and APIs (config, status, play, contact-details) allowed from LAN; integration tests in `lock-admin-localhost.test.js`.
+- [ ] **Centralize notifications/alerts** — All toasts/modals from one module so styling + z-index + behaviour change in one place.
-- [x] **Verify 5+ streams** — Confirmed 6/6 live (VB-Cable A/B, mics). Root cause of "5th fails" was bad device choice, not Icecast limit.
+- [ ] **Internet broadcast tunnel (explore; only if feasible)** — Optional outbound-only tunnel so listeners outside the LAN can listen (e.g. self-hosted frp/ngrok-style relay on a VPS the operator controls). Must stay opt-in, off by default — LANStreamer's core is local, low-latency, private. Research latency + NAT constraints before committing.
-- [x] **Unique stream names** — No duplicate display names (create/update); case-insensitive, trimmed.
+- [ ] **Explore: Listener song requests** — Anyone on the network can request a song; admin grants; listed on listener page. (From PR #12.)
-- [x] **Start/Stop All button** — Start all stopped/error streams; Stop all running; API `POST /api/streams/start-all`; partial-failure toast with names + first error; 150ms delay between success/error toasts.
+- [ ] **Phase 2: cross-platform abstraction** — Device discovery per OS (dshow/avfoundation/pulse; StreamingService hardcodes dshow), config/logs in OS app-data dirs, retire .bat scripts.
-- [x] **Listener page uses LAN IP** — Copy URLs and listener page use `config.host` from getPreferredLANHost / icecast.xml. Docs: "Which IP is my LAN / WiFi?" in TROUBLESHOOTING.md.
+- [ ] **Phase 3: bundle binaries — NEARLY DONE (2026-10-30)** — vendor/ (gyan ESSENTIALS ffmpeg + Icecast kit, stock-parity per the §0.1 decision) + extraResources + data-dir runtime + first-run functional probe (BinaryProbeService) all live; `isIcecastRunning` now credential-verified (zombie-proof). Remaining: pin SHA256 checksums, official Icecast 2.5.0 kit download (2.4.4 EOL 2026-12-31; portable 2.5.0 already validated at ~/Tools/icecast-2.5.0), per-install admin values, GPL LICENSES files inside the installer, download-on-demand UI for probe failures.
-- [x] **Mobile** — Listener page, "Listen to Streams" header link, and Copy URL use correct LAN IP. HeaderComponent fetches config.host; TROUBLESHOOTING.md "Action Required: Mobile Listener Setup". _QA: Test with real device on same WiFi._
+- [ ] **Phase 4: test/CI** — Playwright `_electron` + listener-page web E2E + axe-core + GitHub Actions 3-OS matrix (use `npm run electron:smoke`); electron-updater replaces UpdateService/.bat at packaging. Add E2E regression: machine IP change must not break status polling (covered by localhost polls; test the contract).
-- [x] **Workflow/docs** — Branch workflow: feature → merge into dev locally → push dev → PR dev→main (remote only). Local branches: dev + features only; `main` deleted locally (remote-only). AGENTS.md removed; refs point to CLAUDE.md. PR #6 updated with lock-admin-localhost changes.
-
-- [x] **Notification types** — For duplicate stream name or duplicate source, use a simple modal ("stream already exists") without troubleshooting link; for real failures, existing error handling with diagnosis/link. Implemented in FFmpegStreamsManager: isDuplicateError(), showDuplicateModal(); used for start, restart, update, start-all.
-
-- [x] **Source validation & clear errors** — On stream failure, backend errorDiagnostics provides category (device, connection, auth, etc.), title, solutions; API returns shortMessage; admin dashboard shows error + troubleshooting link. Optional "Test source" button deferred.
-
-- [x] **Timing of Modals** — Alert modals should appear only after the action is performed, not before. All success modals now have 1-second delay after UI updates.
-
-- [x] **Listener: dismiss without reload** — New-stream notification dismisses overlay without full reload (don't stop playback). Hot reload only for the affected stream. Implemented: `dismissNewStreamNotification()` calls `loadStreams()` to refresh without page reload.
-
-- [x] **Error alert UX** — Structured error from API (shortMessage = diagnosis title); admin dashboard shows centred toast with message + link to troubleshooting guide; Start All partial failure lists failed names (up to 5 + "and N more") and first error. Duplicate errors use simple modal without link.
-
-- [x] **Stability** — Confirm 3+ streams stay stable (see TROUBLESHOOTING.md). _CONFIRMED working._
-
-- [x] **Device change mid-stream / Play after edit** — Play proxy now checks Icecast response status; non-200 returns 502 with clear message so listener page no longer shows "Authentication Failed". Listener page shows "Stream not running. Start it on the dashboard, then try Play again." No refresh or delete/recreate needed. _See TROUBLESHOOTING.md §1c._
-
-- [x] **Stream labels (optional)** — Streams show S1, S2, S3 from server order; label in `getStats()` and on listener page / dashboard.
-
-- [x] **Sortable streams (optional)** — Up/down buttons on dashboard; `POST /api/streams/reorder`; order persisted in `config/streams.json` (`_order`); listener page uses same order and S1/S2/S3 labels without refresh.
-
-- [x] **Contact: WhatsApp** — Country code enforced (digits 10–15, no leading zero); validation backend + ContactManager; `wa.me/` built on listener page; placeholder "e.g. +44 7123 456789 (country code required)". Not working
-
-- [x] **Update notification UX** — Bell icon in header; auto-check on load (HeaderComponent.checkForUpdates); when updateAvailable=true bell shows badge and "Update Available"; click opens modal with update info and link to release. Single button id header-update-bell-btn; manual check on click when no update yet.
-
-- [x] **Event Details & Your Contact components** — Not working as they should; details not saving for contact, and the event details collapsible doesn't open after saving details.
-
-- [x] **UI/UX polish (optional)** — [docs/UI-UX-RECOMMENDATIONS.md](docs/UI-UX-RECOMMENDATIONS.md).
+- [ ] **Phase 6: packaging** — Windows NSIS/portable first; unsigned DMG later for savvy Mac users. Telemetry disclosure + LICENSES in installer. Telemetry key ships via `electron:build:win` (auto-injected from POSTHOG_KEY; also reads ~/.secrets/posthog on dev machines).
---
-## Reference
+## Done (2026-10-28 revival)
-- Run `npm test` before releases; [STARTUP-SEQUENCE.md](docs/STARTUP-SEQUENCE.md) for troubleshooting.
-- **Future refactor:** ErrorFactory consistency, remove/trim FFmpegService.js, device mapping extraction, split large HTML/JS — see inline notes in codebase.
+- **Listener page redesigned** — broadcast rows + persistent mini-player (eq bars, both themes, a11y labels); theming foundation (tokens.css, dark/light toggle, pill buttons, logo variants).
+- **Stale-stream / can't-create-stream fixed** — starting a stream now auto-starts Icecast (was: wall-of-text "cannot connect" error). Troubleshooting doc updated.
+- **Doubled audio devices fixed** — FFmpeg 9 changed device-listing format (`[dshow @]`→`[in#0 @]`); parsers updated for both formats + PowerShell fallback output de-duplicated. (Note: `[^]]` regex classes mis-parse on this Node — always use `[^\]]`.)
+- **Add-stream modal decluttered** — Pro-Tip/Virtual-Audio notices moved behind an info icon popover (links to manual-setup docs); redundant "Maximum 50 characters" hints removed (counter exists).
+- **Delete-stream toast** — waits 900ms, verifies the stream is actually gone via status API, then shows `Stream "" deleted`.
+- **Electron: external links** (e.g. "Listen to Streams") open in the system browser.
+- **Telemetry key for packaged builds** — `electron:build:win` injects POSTHOG_KEY from the build environment into the app (scripts/prepare-telemetry-key.mjs); resolution order env → config/telemetry.json → bundled.
+- Reconciled dev/main; merged error-handling branch (68/68 tests); branch cleanup (local = dev only).
+- Dead code removed (SystemService, WebSocketService, FFmpegService); offline UI (vendored Tailwind + fonts, CSP 'self').
+- Phase 1 Electron wrapper (tray, Stop All & Quit, tree-kill, --smoke); stale-hostname bug fixed (localhost polls + hostname auto-sync); log spam fixed; dismissible notices; SVG logo set; env.example; repo cleanup; docs index.
---
-## Earlier (historical)
+## Reference
-Notification timing, LANStreamer.bat updater, Claude hooks, custom-instructions, capacity NaN fix, config capacity fields, shortMessage + troubleshooting link.
+- Run `npm test` before releases; `npm run build:css` after changing Tailwind classes.
+- Versions (2026-10): FFmpeg 9.0.2 latest (app runs on 8.x, fine); Icecast 2.5.0 latest — **2.4.4 EOL 2026-12-31**.
diff --git a/analysis_output/README.md b/analysis_output/README.md
deleted file mode 100644
index 408af6a..0000000
--- a/analysis_output/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# analysis_output
-
-Historical regression analysis for LANStreamer v1.2.0 → v1.2.2 → v1.2.3.
-
-- **REGRESSION_ANALYSIS_SUMMARY.md** — Root cause summary (port 8000 vs 8001), timeline, and findings. Raw diffs and commit lists were removed during cleanup; see this file for the analysis.
diff --git a/analysis_output/REGRESSION_ANALYSIS_SUMMARY.md b/analysis_output/REGRESSION_ANALYSIS_SUMMARY.md
deleted file mode 100644
index a652e00..0000000
--- a/analysis_output/REGRESSION_ANALYSIS_SUMMARY.md
+++ /dev/null
@@ -1,193 +0,0 @@
-# LANStreamer Regression Analysis: v1.2.0 → v1.2.2 → v1.2.3
-
-**Analysis Date:** 2026-01-26
-**Branch:** `analysis/regression-v1.2.0-to-v1.2.3`
-**Status:** ✅ ROOT CAUSE IDENTIFIED
-
----
-
-## Executive Summary
-
-**ROOT CAUSE FOUND:** The regression from v1.2.2 was caused by a **hardcoded port change** from `8000` to `8001` in the FFmpeg Icecast URL. This was subsequently fixed in v1.2.3 by reverting to port `8000`.
-
-### Timeline of Events
-
-| Version | Port | StreamingService.js Line 178 | Status |
-|---------|------|------------------------------|--------|
-| v1.2.0 | `8000` | `icecast://source:hackme@localhost:8000/` | ✅ Working |
-| v1.2.2 | `8001` | `icecast://source:hackme@localhost:8001/` | ❌ **BROKEN** - Connection refused |
-| v1.2.3 | `8000` | `icecast://source:hackme@localhost:8000/` | ✅ Fixed |
-
-### Commit Evidence
-
-**v1.2.2 Release Commit:** `d3ddd9b`
-- "Release v1.2.2: Critical fixes for port conflicts and streaming stability"
-
-**v1.2.3 Port Revert Commit:** `0dc9916`
-- "fix: Revert to Icecast default port 8000, improve connection error message"
-
----
-
-## Detailed Analysis
-
-### 1. Critical Files Changed
-
-#### StreamingService.js (Primary Regression Source)
-
-**v1.2.0 → v1.2.2 Changes (490 lines):**
-- **Line 178:** Port changed from `8000` to `8001` (BROKEN)
-- Added Icecast status checking before stream start
-- Added stderr capture for error diagnostics
-- Added immediate crash detection
-- Added Windows crash exit code handling (0xA7F00008)
-- Added enhanced error messages with dependency chains
-
-**v1.2.2 → v1.2.3 Changes (46 lines):**
-- **Line 178:** Port reverted from `8001` to `8000` (FIXED)
-- Added AudioDeviceService cache lookup for device names
-- Added VB-Audio Virtual Cable variants
-- Enhanced connection error messages with port mismatch detection
-
-### 2. errorDiagnostics.js Finding
-
-**CRITICAL DISCOVERY:** `errorDiagnostics.js` did NOT exist in v1.2.0, v1.2.2, or v1.2.3.
-
-- Added **after** v1.2.3 in commit `3732460`
-- Therefore, it **cannot be the cause** of the v1.2.0 → v1.2.3 regression
-- This file was added as part of post-v1.2.3 troubleshooting improvements
-
-### 3. Dependency Analysis
-
-**package.json comparison:**
-- v1.2.0: `"version": "1.2.0"`
-- v1.2.2: `"version": "1.2.2"`
-- v1.2.3: `"version": "1.2.3"`
-
-**No dependency changes detected.** All runtime dependencies remained identical across versions.
-
-### 4. Other File Changes
-
-**IcecastService.js:** Only 3 lines changed (minor adjustments)
-
-**FFmpegStreamsManager.js:** Minor UI improvements and timeout adjustments
-
----
-
-## Root Cause Analysis
-
-### The Bug
-
-```javascript
-// v1.2.2 - BROKEN
-const icecastUrl = `icecast://source:hackme@localhost:8001/${streamId}`;
-
-// v1.2.0 and v1.2.3 - WORKING
-const icecastUrl = `icecast://source:hackme@localhost:8000/${streamId}`;
-```
-
-### Why This Caused Failure
-
-1. **Icecast Default Port:** Icecast server runs on port **8000** by default
-2. **icecast.xml Configuration:** The `` setting in icecast.xml defaults to 8000
-3. **Connection Refused:** FFmpeg trying to connect to port 8001 when Icecast listens on 8000
-4. **Error Output:** "connection refused" or "error number -138"
-
-### Impact
-
-- Streams could not connect to Icecast server
-- All stream start attempts failed immediately
-- Error messages were confusing (showed "connection refused" without clear port mismatch indication)
-
----
-
-## Version Status Assessment
-
-Based on the analysis, here's the actual status of each version:
-
-| Version | Functional Status | Notes |
-|---------|------------------|-------|
-| v1.2.0 | ✅ Working | Port 8000, stable baseline |
-| v1.2.2 | ❌ Broken | Port 8001 - connection failures |
-| v1.2.3 | ✅ Working | Port 8000 - port issue fixed |
-
-**Conclusion:** v1.2.3 is **NOT** "less functional" than v1.2.2. v1.2.3 actually **fixed** the port regression introduced in v1.2.2.
-
-If the user is experiencing issues with v1.2.3, those issues are:
-1. Unrelated to the port regression (which was fixed)
-2. Possibly related to other configuration issues
-3. May be due to local environment differences
-
----
-
-## Recommendations
-
-### For Current v1.2.3 Issues
-
-If users are experiencing problems with v1.2.3:
-
-1. **Verify Icecast Port:**
- ```bash
- # Check icecast.xml configuration
- grep -E "|" config/icecast.xml
- ```
-
-2. **Verify .env Configuration:**
- ```bash
- # Check if ICECAST_PORT is set correctly
- grep ICECAST_PORT .env
- ```
-
-3. **Test Icecast Directly:**
- ```bash
- # Test if Icecast is responding
- curl http://localhost:8000
- ```
-
-### Code Improvements Needed
-
-1. **Remove Hardcoded Port:**
- - Current code hardcodes `localhost:8000`
- - Should read from `icecast.xml` or `.env` dynamically
-
-2. **Add Port Configuration Validation:**
- - Warn if Icecast port doesn't match FFmpeg URL port
- - Provide clear error messages on port mismatch
-
-3. **Enhanced Error Message (v1.2.3 already improved this):**
- ```javascript
- 🔧 COMMON CAUSES:
- 1. Icecast not running - Start it from the dashboard
- 2. Port mismatch - LANStreamer uses port 8000 by default
- • Check in your icecast.xml matches 8000
- • Or set ICECAST_PORT=xxxx in your .env file
- ```
-
----
-
-## Files Generated
-
-All analysis outputs saved in `analysis_output/`:
-
-- `CHANGES_1.2.0_to_1.2.2_STAT.txt` - File changes statistics
-- `CHANGES_1.2.2_to_1.2.3_STAT.txt` - File changes statistics
-- `diff_StreamingService_*.patch` - StreamingService.js diffs
-- `diff_errorDiag_*.patch` - errorDiagnostics.js comparisons (empty - didn't exist)
-- `commits_*.txt` - Commit history between versions
-- `all_commits.csv` - All commits with timestamps
-- `package_*.json` - Package.json from each version
-- `error_patterns_comparison.txt` - Error pattern analysis
-- `pattern_order_comparison.txt` - Pattern order verification
-
----
-
-## Next Steps
-
-1. ✅ Root cause identified (port mismatch)
-2. ✅ v1.2.3 already fixed the issue
-3. Consider adding dynamic port configuration
-4. Add port mismatch validation and warnings
-5. Test v1.2.3 with proper Icecast configuration
-
----
-
-**Analysis Complete:** The regression was caused by a port change in v1.2.2 (8000→8001) and was fixed in v1.2.3 (8001→8000).
diff --git a/docs/APP-FLOW.md b/docs/APP-FLOW.md
new file mode 100644
index 0000000..29787d0
--- /dev/null
+++ b/docs/APP-FLOW.md
@@ -0,0 +1,157 @@
+# LANStreamer App Flow
+
+Purpose: single map of every page, user flow, and component — the source of truth for the UI redesign and for generating design prompts (Lovable/Nanobanana/Mobbin references). Last updated: 2026-10-28.
+
+---
+
+## 1. Pages
+
+| Page | URL | Audience | Auth | File |
+|------|-----|----------|------|------|
+| Admin Login | `/login` | Operator | credentials → JWT | `public/login.html` |
+| Admin Dashboard | `/dashboard` (also `/`) | Operator | localhost-only (`requireLocalhostAdmin`) | `public/index.html` |
+| Listener Page | `/streams` | Anyone on LAN | none | `public/streams.html` |
+
+The **Electron desktop app** (packaged) opens `/dashboard` in its own window on the operator's machine; listeners always use their phone/PC browser on the LAN. Same pages either way.
+
+---
+
+## 2. Primary flows
+
+### 2.1 Operator: first run
+
+```mermaid
+flowchart TD
+ A[App installed / first launch] --> B{Telemetry consent prompt}
+ B -->|Allow| C[Telemetry ON]
+ B -->|Decline| D[Telemetry OFF]
+ C --> E[Environment check]
+ D --> E
+ E --> F{FFmpeg found?}
+ F -- no --> F1[Error card: install link + diagnosis]
+ F -- yes --> G{Icecast found?}
+ G -- no --> G1[Setup panel: search / custom path]
+ G -- yes --> H[Dashboard ready state]
+ H --> I[Security warning if default creds]
+```
+
+### 2.2 Operator: start a stream
+
+```mermaid
+flowchart TD
+ A[Dashboard] --> B[Click Start New Stream]
+ B --> C[Add Stream modal]
+ C --> D[Pick audio device / file]
+ D --> E{Optional: Test Source (Show test tools toggle)}
+ E --> F[Set name, quality, bitrate]
+ F --> G[Click Go Live]
+ G --> H{Capacity check Icecast running?}
+ H -- no --> X1[Error: start Icecast first + quick fix]
+ H -- full --> X2[Error: source limit reached + capacity context]
+ H -- ok --> I[Device accessibility test]
+ I -- fail --> X3[Device error + diagnosis modal (solutions, stderr, guide link)]
+ I -- pass --> J[FFmpeg spawn → push to Icecast]
+ J --> K[Stream card: LIVE badge, uptime, listeners, stop/edit]
+ K --> L{Duplicate name/source?}
+ L -- yes --> X4[Simple duplicate modal]
+```
+
+### 2.3 Listener: tune in
+
+```mermaid
+flowchart TD
+ A[Phone browser on LAN] --> B[Open http://LAN-IP:3001/streams]
+ B --> C[Event title/subtitle + event image or brand mark]
+ C --> D[Stream list S1..Sn with LIVE state]
+ D --> E[Press Play on a stream]
+ E --> F{Stream actually running?}
+ F -- no --> G[Inline msg: start it on dashboard]
+ F -- yes --> H[Audio plays via play proxy volume slider + mute persist]
+ H --> I[New stream appears? → dismissible notification, no reload]
+```
+
+### 2.4 Shutdown (Electron tray mode)
+
+```mermaid
+flowchart TD
+ A[Close window] --> B[Hide to tray streams keep serving]
+ B --> C{User action}
+ C -- Show Dashboard --> D[Window restored]
+ C -- Stop All & Quit --> E[stopAllStreams → Icecast stop → tree-kill leftovers → app exit]
+```
+
+---
+
+## 3. Dashboard layout (current)
+
+```
++----------------------------------------------------------------------+
+| HEADER: logo | Icecast status pill | ffmpeg status | update bell |
++----------------------------------------------------------------------+
+| SECURITY WARNING (dismissible) — if default creds |
++----------------------------------------------------------------------+
+| STREAMS CARD | EVENT PANEL |
+| toolbar: [Show test tools][Refresh][Start/Stop All] | (image, |
+| stream rows: S1..Sn | title, |
+| [LIVE badge] name | uptime | listeners | about) |
+| [play/stop][edit][reorder ↑↓][delete] +---------------+
+| empty state: Quick Start guide (dismissible) | CONTACT & |
+| | FEEDBACK |
+| ICECAST CARD: start/stop, mounts, capacity | (collapsed) |
++----------------------------------------------------------------------+
+| FOOTER: version | GitHub link |
++----------------------------------------------------------------------+
+```
+
+## 4. Listener layout (current)
+
+```
++----------------------------------------------+
+| HEADER: logo | Listen to Streams link |
++----------------------------------------------+
+| Event title + subtitle |
++----------------------+-----------------------+
+| STREAM CARDS | EVENT IMAGE / |
+| S1 [LIVE] name | brand mark default |
+| [▶ Play] +-----------------------+
+| per-card: volume, | ABOUT (default text) |
+| mute +-----------------------+
+| S2 ... | CONTACT & FEEDBACK |
+| | (collapsed default) |
++----------------------+-----------------------+
+| FOOTER: version | GitHub | license |
++----------------------------------------------+
+```
+
+**Redesign note (Mobbin + Stemtracks direction):** listener page should get a sticky bottom mini-player (Sonos/Spotify pattern) so controls survive scrolling; one dominant Play per card; LIVE = color + text, never dot-only.
+
+---
+
+## 5. Component map
+
+| Component | File | Used by | Notes |
+|-----------|------|---------|-------|
+| FFmpegStreamsManager | `components/FFmpegStreamsManager.js` | Dashboard | stream CRUD, start/stop/reorder, modals, Test Source, Quick Start |
+| IcecastManager | `components/IcecastManager.js` | Dashboard | start/stop, mounts, capacity, install search |
+| EventManager | `components/EventManager.js` | Dashboard | event title/subtitle/about/image (persisted `config/`) |
+| ContactManager | `components/ContactManager.js` | Dashboard | WhatsApp/phone/email shown on listener page |
+| HeaderComponent | `components/HeaderComponent.js` | Both | logo, status pills, update bell |
+| FooterComponent | `components/FooterComponent.js` | Both | version, links |
+| UpdateNotification | `components/UpdateNotification.js` | Dashboard | GitHub release check |
+| LobbyMusicPlayer | `components/LobbyMusicPlayer.js` | Dashboard | file-playback preview |
+| FileBrowser | `components/FileBrowser.js` | Dashboard | pick input file |
+| ComponentManager | `components/ComponentManager.js` | Dashboard | lifecycle orchestration |
+| LSNotices | `assets/js/notice-dismiss.js` | Both | dismissible notices w/ Show stubs |
+| StreamListener (inline) | `streams.html` | Listener | play proxy, volume, new-stream notif |
+
+## 6. Backend services (context for redesigners)
+
+| Service | Role |
+|---------|------|
+| `StreamingService` | FFmpeg spawn/lifecycle, formats (MP3/AAC/OGG), persistence, capacity |
+| `IcecastService` | install detection, start/stop, stats (localhost polls), hostname auto-sync, security check |
+| `AudioDeviceService` | device discovery (dshow; wasapi fallback) |
+| `UpdateService` | GitHub release polling (to be replaced by electron-updater) |
+| `TelemetryService` | PostHog, opt-in, anonymous ID, queue-and-flush |
+
+API surface used by the UI: `/api/streams/*` (status, start, stop, start-all, stop-all, reorder, play/:id proxy), `/api/system/*` (config, icecast start/stop/status, audio-devices, security-check), `/api/settings/*`, `/api/contact-details`, `/api/auth/login`.
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 017dccb..c63a2b6 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -5,15 +5,25 @@ All notable changes to LANStreamer will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-## [Unreleased]
-
-### Planned
-- Stream configuration and mount point management
-- FFmpeg integration for audio streaming
-- Listener web player interface
-- QR code generation for listener access
-- Real-time stream monitoring and statistics
-- Final packaging as standalone `.exe`
+## [2.0.0] — 2026-11-01 (first packaged release)
+
+Everything below ships in the Windows installer and standalone builds. For the release process, see [GO-LIVE-CHECKLIST.md](./GO-LIVE-CHECKLIST.md).
+
+### Added — the Electron desktop app
+- Full Electron shell: dashboard window, tray icon (hide-to-tray, Stop All & Quit), single-instance lock, first-run telemetry notice (ON by default, one-click off), graceful shutdown that stops streams + Icecast
+- **Bundled binaries:** the installer ships FFmpeg + the Icecast kit (extraResources), with runtime resolution preferring the bundle over system installs — a fresh machine needs NOTHING pre-installed. Bundled Icecast runs from a writable per-user config/log dir (no more Program Files EPERM), and all mutable state (streams, device config, contact details, uploads, telemetry consent) lives in `%APPDATA%/LANStreamer` on packaged installs
+- Admin authentication: login page, JWT session (7-day), localhost lock so admin APIs/dashboard refuse non-localhost connections; default-credentials banner with change instructions; logout
+- **PostHog telemetry (ON by default, opt-out — owner decision 2026-11-01):** server events (app start, stream started/stopped/failed with error category) and **listener failure reports** (playback error with media code + browser, buffer stalls, off-air grace/give-up, page-load failures) relayed through the operator's server; distributed installs get telemetry via a bundled build key (asar path fix); first run shows an informational notice with one-click Turn-off
+- Event banner system: operator-uploaded artwork with lightbox, bundled default banner when none set
+- In-app guide page (`/docs`), QR code sharing, share card that tracks the PC's current LAN address
+
+### Changed — 2026 redesign
+- Complete UI redesign (operator dashboard + listener page): token-based design system, status strip, grouped stream rows with pinned-right row actions, side drawer for stream creation, listener hero + channel picker with visible play affordances, sticky opaque headers, flat surfaces (no card shadows/hover/animations), full light/dark themes, fully offline (all fonts/assets vendored)
+- Process management hardened: Windows process-tree kills in the right order (no more orphaned FFmpeg holding audio devices), icecast self-healing on stream start/restart, stale LAN IP detection when the network changes
+- **Low-latency playback (2026-10-30):** listener audio delay cut from a reported 4–5 s to ~1 s class — MSE-based player keeps ~0.5 s buffered ahead (vs ~2.3 s browser default, measured) and snaps back to the live edge after WiFi jitter or pauses; FFmpeg capture runs with low-delay flags (`nobuffer`, `low_delay`, `probesize 32k`, `analyzeduration 0`, `flush_packets 1`); the play proxy disables Nagle and flushes headers; bundled Icecast uses a 16 KB join burst. Safari/iOS automatically use the classic direct-stream path
+
+### Known gaps
+- macOS/Linux support is source-only
---
diff --git a/docs/GO-LIVE-CHECKLIST.md b/docs/GO-LIVE-CHECKLIST.md
new file mode 100644
index 0000000..43c165a
--- /dev/null
+++ b/docs/GO-LIVE-CHECKLIST.md
@@ -0,0 +1,126 @@
+# 🚀 Go-Live Checklist — before bundling & shipping LANStreamer
+
+Working document for the first packaged release of the **Electron desktop app**. Version: **2.0.0** (bumped in package.json 2026-10-31 — Jerry's call: the redesign + desktop-app transformation is a MAJOR release; the old `1.2.4 → 1.3.0` minor target is superseded). Work through every section; tick items only with evidence (test run, screenshot, command output).
+
+> Run the automated suite first — it clears most regressions in minutes:
+> `npm test` → then `npm run electron:smoke` → then the verify scripts in [README-DEVELOPERS.md](./README-DEVELOPERS.md) against a fresh server.
+
+---
+
+## 0. Security must-fixes (external review 2026-10-29 — block shipping until done)
+
+1. ~~**Bind bundled Icecast to loopback + random per-install passwords.**~~ **SHIPPED (Jerry's final decision, 2026-10-30 — supersedes the earlier same-day "ship stock" call): public software shipping known-default Icecast credentials is hackable by anyone who knows the app.** The generated bundled config now binds `127.0.0.1` (listeners receive audio through the :3001 play proxy — never Icecast directly) and randomizes source/relay/admin passwords per install (`ensureVendoredIcecastConfig`; the app parses them itself, nobody types them). Unit-tested (`vendorPaths.test.js` hardening contract) + live-verified. OWN system Icecast installs keep their own config — the dashboard warns while stock credentials are active there.
+2. **Binary provenance:** pin SHA256 for the FFmpeg download (fail build on mismatch); replace "copy Icecast kit from maintainer's machine" with a pinned official-kit download + hash; switch to the gyan **essentials** build (clean GPL redistribution, ~48 MB). **Status:** FFmpeg essentials + pinned SHA256 SHIPPED (`src/utils/binaries.js`); Icecast kit still copied from the validated local 2.5.0 portable — pinned official-kit download remains open.
+3. **Icecast 2.4.4 is end-of-support 2026-12-31** (and has CVE history) — bundle 2.5.x. **SHIPPED:** vendor kit is 2.5.0.
+4. ~~**Packaged installs cannot use `.env`** — the "change admin credentials" path is impossible there.~~ **RESOLVED (2026-10-30, final policy): documented defaults + prompt to change + in-app change + documented recovery.** The *Admin account* card changes the login in-app (scrypt-hashed in the data dir, JWT secret rotates). Random per-install admin minting was tried and REVERTED the same day as overkill — the localhost lock already keeps the LAN out of the admin panel, and the operator must stay in full control. Forgot-password recovery: delete `security.json` (path shown on the localhost-only login page + README + /docs) → documented defaults return → change again in-app. E2E: `scripts/verify-admin-creds.mjs`.
+5. **GPL artifacts inside the installer:** ship FFmpeg/Icecast license texts + source-offer, not just release-note credit. **SHIPPED:** `vendor/licenses/` (GPL-2.0/3.0 texts + source-offer README) rides extraResources.
+6. Ship **SHA256SUMS** alongside release artifacts (cheap unsigned-installer mitigation).
+
+---
+
+## 1. Clean-slate functional pass (on the dev machine)
+
+Start from a pristine state — most "bugs" this project has hit were dirty-state artifacts (leftover servers, stale config, cached tabs).
+
+- [ ] Kill every LANStreamer instance first: `netstat -ano | findstr :3001 :3002 :8200` → nothing listening; `tasklist | findstr /i "ffmpeg icecast"` → nothing running
+- [ ] Fresh app launch (`npm run electron:dev`): dashboard window opens, boot screen resolves, version label shows
+- [ ] Login: wrong password rejected; `admin` / `lanstreamer123` accepted; logout works; token survives app restart (7-day session)
+- [ ] First-run banner shows while defaults are active; disappears after changing credentials via `.env`
+- [ ] Stream lifecycle: **Add stream** (Save, stays stopped) → **Go live** → status LIVE + uptime ticking → **Stop** → **Retry** → edit (change input) → duplicate → reorder (Move up/down) → delete. No button ever hangs (all mutating calls have timeouts)
+- [ ] Start All / Stop All with 2+ streams
+- [ ] Every stop/quit leaves **zero orphaned `ffmpeg.exe`** in Task Manager (this was the zombie-device bug — verify after every stop path, including edit-while-live and quit-while-live)
+- [ ] **Crash-path orphan test:** Task Manager → End task on LANStreamer mid-stream → relaunch → stale children are cleaned. *(Startup sweep SHIPPED: Electron main kills orphaned ffmpeg/icecast matched by vendored executable path — never by process name. This item now just verifies it works.)*
+- [x] **Sleep/hibernate mid-broadcast:** SHIPPED — `powerSaveBlocker` (prevent-app-suspension) engages while any stream is live and releases when none are; on resume, streams that were live before suspend are auto-restored after a 5s device-settle delay
+- [ ] **Non-ASCII paths:** test with a Windows username containing spaces + non-ASCII (e.g. `José Müller`) and a Unicode dshow device name — spawn quoting and icecast config paths are classic failure points
+- [ ] Error path: start a stream on a device already held by another app → friendly busy error with **Change input** / **Retry**, full diagnostic collapsed behind a link to /docs
+- [ ] Audio inputs card (under the streams card): collapsed by default, opens/closes, rescan works without toggling the card, IN USE / IDLE / MISSING statuses correct
+- [ ] Event details + feedback contact cards save and show on the listener page; banner upload → cover display → lightbox; remove image → bundled default banner appears
+- [ ] Icecast info card shows running status, listeners count, uptime
+
+## 2. Listener experience (real devices, not just devtools)
+
+- [ ] Open `http://:3001/streams` on **Android Chrome, iOS Safari, and a desktop browser**
+- [ ] **iOS specifics:** audio continues on lock screen? Silent-switch behavior? MediaSession/now-playing metadata (nice-to-have)
+- [ ] Channel rows show LIVE chips, uptime, bitrate; visible play circles; icon flips play ⇄ pause correctly on every tap (pause→play flip was a real bug — test the cycle)
+- [ ] Switching channels mid-play; big player reflects the change; mini-player on mobile while scrolled
+- [ ] Kill the stream on the dashboard while a listener is playing → listener sees "went off air — waiting…", grace countdown, then "off air, will resume"; restart the stream → auto-resumes without user action
+- [ ] Pause a listener → it never auto-resumes until they press play
+- [ ] QR code: scan with a phone camera → opens the listener page directly
+- [ ] Both themes (dark/light) on every listener surface — dark-on-dark / light-on-light contrast bugs are this project's most-reported class
+- [ ] 3+ simultaneous listeners for 15+ minutes: audio stays in sync, no memory creep in Task Manager (node + ffmpeg)
+
+## 3. Security pre-flight
+
+- [ ] Change the default admin credentials (`ADMIN_USERNAME` / `ADMIN_PASSWORD` / `JWT_SECRET` in `.env`) and confirm the banner retires
+- [ ] From a **different machine** on the LAN: `/streams` loads (public) but `/dashboard` and admin APIs are refused (localhost lock) — `curl http://:3001/dashboard` from another device must NOT render the dashboard
+- [ ] Listener page never displays credentials anywhere
+- [ ] `git status` clean of secrets; `electron/telemetry-key.json` and `.env` are gitignored (verify: `git check-ignore electron/telemetry-key.json .env`)
+- [ ] Rate-limited telemetry endpoint sane: `for i in {1..35}; do curl -s -o /dev/null -w "%{http_code} " -X POST http://localhost:3001/api/telemetry/client-event -H "Content-Type: application/json" -d "{\"event\":\"playback_stalled\"}"; done` → ends in 429
+
+## 4. Telemetry (PostHog — eu.posthog.com)
+
+- [ ] `node scripts/prepare-telemetry-key.mjs` reports "Injected for packaged build" (bundles the key from the credential store; file gitignored)
+- [ ] With telemetry ON (tray toggle): events visible in PostHog Live within ~30s — `lanstreamer_app_start`, `stream_started` / `stream_failed` when you exercise streams
+- [ ] Trigger a listener playback failure (or run `scripts/verify-client-telemetry.mjs`) → `lanstreamer_client_*` events arrive with `surface=listener`
+- [ ] With telemetry OFF (tray toggle): no events arrive at all; app behaves identically (telemetry must never affect function)
+- [ ] README "Telemetry & Privacy" matches what's actually collected (it does as of this writing — re-read after any telemetry change)
+
+## 5. Resilience & environment
+
+- [ ] Quit app mid-stream (tray → Stop All & Quit) → zero orphaned processes; relaunch → auto-start streams restore (if `autoStart` set)
+- [ ] Close the window (not quit) → app hides to tray, streams keep serving; listeners confirm audio continues
+- [ ] Change network (different subnet / hotspot): share card + QR update to the new LAN IP; old links fail gracefully
+- [ ] Port collision: start a second instance → it must not corrupt the first (single-instance lock) and the "port in use" guidance appears in /docs
+- [ ] Windows Firewall prompt on first run: accept for **Private networks**; listener on another device confirms reachability
+- [ ] **Public-profile gotcha:** café/conference/hotspot networks default to the Public profile → inbound 3001 silently blocked. Verify reachability on a hotspot; document "set network profile to Private" for operators
+- [ ] **AV/MOTW pass:** clean-VM test with Defender real-time protection ON — unsigned vendored exes spawning from `resources\` are false-positive territory; verify the downloaded-from-GitHub flow end-to-end (Mark-of-the-Web can block child exes from extracted archives)
+- [ ] Offline check: `node scripts/verify-offline.mjs` — app fully renders with all non-localhost requests blocked (fonts/assets vendored)
+- [ ] Reboot the operator PC with the app configured: relaunch and confirm streams/config persist (config/ survives)
+
+## 6. Packaging (NSIS installer + portable — bundles FFmpeg + Icecast)
+
+The installer carries everything: `electron:build:win` auto-runs `fetch-vendor-binaries.mjs` (fills gitignored `vendor/` with FFmpeg + the Icecast kit and a **clean stock** icecast.xml — never the local machine's passwords) then `prepare-telemetry-key.mjs`, then electron-builder packs `vendor/` as extraResources. At runtime the app prefers the bundled binaries (explicit `FFMPEG_PATH` / `ICECAST_EXE_PATH` env still wins) and keeps all mutable state in `%APPDATA%/LANStreamer` — nothing writes next to the exe.
+
+- [ ] `npm test` green immediately before building
+- [ ] `npm run electron:build:win` → installer + portable in `release/`; installer size sane (target ~100 MB once the bundle switches FULL → essentials ffmpeg and drops ffplay/ffprobe; ~230 MB with today's FULL build)
+- [x] **Binary strategy — SHIPPED (2026-10-30):** first-run functional probe (dshow devices / encoder chain / 2 s end-to-end against a throwaway loopback icecast; ~3.7 s measured, non-blocking) with the result pinned to `binary-probe.json` and re-run only on stale pins; resolution order env → vendored → probe-passed system → download prompt; `GET /api/system/binary-probe` for support. Essentials FFmpeg verified on the maintainer's real machine (all stages pass, real stream, listener playback). Remaining: the download-on-demand UI for the (rare) probe-failure tier.
+- [x] Electron locales trimmed to en-US (`electronLanguages`) — shipped 07f2d6e
+- [x] Default event banner recompressed (1.27 MB → 188 KB, 2400 px) — shipped 07f2d6e
+- [ ] **Install on a clean Windows machine (or VM) with NOTHING pre-installed** — no Node, no FFmpeg, no Icecast. This is the single most important check ("works on my PC" insurance). On that machine:
+ - [ ] App launches, dashboard opens, login works, version shows correctly (from package.json, not "unknown")
+ - [ ] First-run telemetry consent dialog appears (bundled key resolves) — test BOTH Allow and Decline paths
+ - [ ] Create a stream and go live **using only the bundled binaries**; a phone plays it (check Task Manager: ffmpeg.exe and icecast.exe run from the install's `resources\vendor\`)
+ - [ ] All config/uploads land in `%APPDATA%/LANStreamer` (delete + reinstall the app → streams and settings survive)
+- [ ] Confirm the build does NOT contain `.env`, the dev machine's `config/`, `public/uploads/`, or a real-credential icecast.xml (inspect the installer's resources)
+- [ ] SmartScreen will warn on an unsigned exe — decide: accept for now (document in release notes: "More info → Run anyway") or invest in code signing later
+- [ ] Portable build: runs from a folder without installing; config lands somewhere sensible and persists between runs (decide: true-portable via `PORTABLE_EXECUTABLE_DIR` vs `%APPDATA%`, and document)
+- [ ] **Upgrade path:** build two dummy versions, NSIS over-install test (old → new: settings survive, no duplicate entries)
+- [ ] **Uninstall story:** what uninstall leaves behind (`%APPDATA%/LANStreamer` stays — intentional? document)
+- [ ] **Source-install migration:** existing source/ZIP users have config in `./config/` — either migrate to `%APPDATA%` on first packaged run or document "not migrated, set streams up again"
+- [ ] **Build the release artifact the way CI would** (or add CI packaging) — don't ship from an environment CI never exercised
+- [ ] Release notes must credit the bundled GPL binaries (FFmpeg gyan.dev build, Icecast) with their licenses
+
+## 7. Release: version, tag, notes on GitHub
+
+- [ ] Bump `version` in **package.json** (already bumped to 2.0.0 — verify the installer filename says 2.0.0)
+- [ ] Move `[Unreleased]` in [CHANGELOG.md](./CHANGELOG.md) to `## [2.0.0] - `; write the user-facing highlights (Electron app, admin login, redesign, listener page, telemetry opt-in, default event banner)
+- [ ] Update README if anything user-facing changed (credentials section, download link once releases exist)
+- [ ] Merge `dev` → `main` via PR (never push straight to main); CI green on the PR
+- [ ] Tag and push: `git tag v2.0.0 && git push origin v2.0.0`
+- [ ] Create the GitHub release with the installers attached and real release notes:
+ ```bash
+ gh release create v2.0.0 release/*.exe release/*.yml SHA256SUMS.txt \
+ --title "LANStreamer v2.0.0 — desktop app" \
+ --notes-file release-notes-v2.0.0.md
+ ```
+- [ ] Generate and attach **SHA256SUMS.txt** for all release artifacts (partial SmartScreen mitigation for an unsigned installer)
+- [ ] Release notes template (user-facing, non-technical): **What's new** (5–8 bullets) · **Installing** (nothing to pre-install — FFmpeg + Icecast come bundled; SmartScreen note) · **Upgrading from a source/ZIP install** · **Known issues** · **Telemetry disclosure** (opt-in, what's collected, how to decline; Decline must persist across app updates) · **Licenses** (bundled FFmpeg/Icecast are GPL — offer in notes, texts inside the installer)
+- [ ] Smoke the release as a stranger would: fresh VM, download the installer **from the GitHub release page**, install, run one stream end-to-end
+- [ ] Post-release: watch PostHog for `app_start` from install IDs that aren't yours; triage `stream_failed` / `lanstreamer_client_*` events as user reports come in
+
+## 8. Deferred (explicitly NOT blocking this release)
+
+- Code signing certificate (SmartScreen reputation builds over time; signing is a follow-up)
+- macOS/Linux packaging (source-only for now)
+- Auto-update via electron-updater (update checks point at GitHub releases today)
+- PWA for listeners (deliberately removed — DHCP IP changes break it; see docs)
diff --git a/docs/LATENCY.md b/docs/LATENCY.md
new file mode 100644
index 0000000..c3f828a
--- /dev/null
+++ b/docs/LATENCY.md
@@ -0,0 +1,57 @@
+# Latency in LANStreamer
+
+What affects the delay between the operator's audio and what listeners hear, and what can be done about it — split into what **we control** (app side) and what **the operator/event setup controls** (their side). Research date: 2026-10-28. References at the end.
+
+## Where latency comes from (total = sum of all stages)
+
+```mermaid
+flowchart LR
+ A[Audio device capture] --> B[FFmpeg encode buffer]
+ B --> C[Icecast server queue + burst/prebuffer]
+ C --> D[Network transfer LAN]
+ D --> E[Browser player buffer]
+ E --> F[Listener hears it]
+```
+
+Encoder buffer + server queue + burst/prebuffer + player buffer dominate; the LAN network itself is usually < 5 ms.
+
+## App side (what LANStreamer can do)
+
+**Status 2026-10-30: the low-latency round SHIPPED.** Measured on a live stream (Chromium, `scripts/verify-latency.mjs`): buffered-ahead in the player dropped from **~2.3 s (browser default) to ~0.5 s steady**, time-to-first-audio ~1.6 s after the tap. Architecture floor with MP3-over-HTTP is ~0.8–1.2 s end-to-end; going below that means changing transport (WebSocket/WebRTC + Opus), not tuning.
+
+| Lever | Status (2026-10-30) | Trade-off |
+|---|---|---|
+| **Listener player (the big lever)** | ✅ SHIPPED — MSE-based playback (`public/assets/js/lowlatency.js`): the page fetches the play-proxy stream itself and appends ~0.5 s chunks to a MediaSource buffer, snapping the playhead back to the live edge whenever drift exceeds ~0.65 s (rate-limited to 1/s). Safari/iOS (no MP3-in-MSE) and any MSE failure fall back to the plain `` path automatically | Occasional tiny audible skip when snapping back to live after WiFi jitter — the cost of staying live instead of drifting seconds behind |
+| **FFmpeg capture flags** | ✅ SHIPPED — `-fflags nobuffer -flags low_delay -probesize 32k -analyzeduration 0` before the dshow input, `-flush_packets 1` on output (both input paths). Validated live against a real VB-Cable capture | Validated on this machine's devices; exotic capture devices should be re-tested (regression test: `tests/integration/ffmpeg-spawn.test.js`) |
+| **Express play proxy** | ✅ SHIPPED — `flushHeaders()`, `socket.setNoDelay(true)` (Nagle cost 40–200 ms per small MP3 frame), `Cache-Control: no-store` | — |
+| **Icecast `burst-on-connect` / `burst-size`** | ✅ SHIPPED (bundled template) — burst stays ON with a 16 KB burst (≈0.7 s at 128k) instead of the stock 64 KB (≈4 s pre-pushed on join) | 0 would shave a little more but listeners take 1–2 s longer to first hear audio |
+| **Icecast `queue-size`** | Stock 512 KB (it is a backlog CAP, not added latency — leave it) | — |
+| **Bitrate / codec** | MP3 128–192 kbps stays the balance; Opus would cut ~0.1–0.3 s but Icecast+browser support is spotty | Lower bitrate (64–96 kbps) for many-listener events |
+| **FFmpeg pacing (`-re`)** | Device capture is inherently real-time; `-re` only on the file-input path | — |
+
+**Remaining idea (bigger rewrite):** WebSocket/WebRTC + Opus transport for ~200–400 ms — see the UX audit P4/deferred list; only worth it if same-room interpretation demands sub-second.
+
+## Operator/event side (beyond our control — guide them)
+
+From research on wireless audio latency (see references):
+
+1. **Use 5 GHz WiFi** for listeners where available; 2.4 GHz is congested (microwaves, neighbouring networks).
+2. **Router QoS**: prioritize the server machine's traffic; or better —
+3. **Dedicated WiFi network / hotspot** for the event. A phone-hotspot or spare router purely for streaming beats a busy venue network.
+4. **Wired where possible**: the *operator* machine to the router via Ethernet removes the biggest variable. Listeners are inherently wireless.
+5. **Placement**: line of sight between listeners and the AP; elevate the AP; keep it away from microwaves/other transmitters; minimise distance.
+6. **Limit listener count per AP** (~20–25 phones per consumer AP for audio); add a second AP on a different channel for larger events.
+7. **Update firmware/drivers** on router and audio devices.
+8. **Measure, don't guess**: latency-testing apps + watching for stutter tells you whether the problem is network (stutter, drops) or config (constant offset).
+
+Constant ~1–3 s offset = buffering config (burst/prebuffer). Stutter/drops = WiFi capacity/interference. That distinction tells you which side to fix.
+
+## References
+
+- [Fixing streaming latency in wireless audio systems — TechTaps](https://techtaps.com/how-to-fix-streaming-latency-issues-in-wireless-audio-systems/)
+- [Icecast config reference (burst-on-connect, burst-size, queue-size)](https://github.com/AzuraCast/icecast-kh-ac/blob/main/doc/icecast2_config_file.html)
+- [Icecast Streaming Handbook](https://we.riseup.net/assets/29773/Icecast-Streaming-Handbook)
+- [LibreTime: Icecast tuning discussion](https://github.com/libretime/libretime/issues/540)
+- [Low-latency Icecast streaming thread (RTLSDR)](https://www.reddit.com/r/RTLSDR/comments/zwv0ut/low_latency_streaming)
+- [FFmpeg to Icecast usage — ffmpeg-user list](https://ffmpeg.org/pipermail/ffmpeg-user/2019-June/044578.html)
+- [Liquidsoap clock docs (source pacing)](https://www.liquidsoap.info/doc-dev/clocks)
diff --git a/docs/README-DEVELOPERS.md b/docs/README-DEVELOPERS.md
new file mode 100644
index 0000000..56d176d
--- /dev/null
+++ b/docs/README-DEVELOPERS.md
@@ -0,0 +1,225 @@
+# LANStreamer — Developer Guide
+
+Technical documentation for anyone working **on** LANStreamer (running from source, testing, contributing). If you just want to install and use the app, see the main [README](../README.md). Shipping a release? Follow **[GO-LIVE-CHECKLIST.md](./GO-LIVE-CHECKLIST.md)**.
+
+---
+
+## 🚀 Technical Quick Start
+
+**Prerequisites:** Node.js 18+, plus FFmpeg and Icecast available on your machine (see [Installation Guides](guides/README.md); paths can be overridden with `ICECAST_EXE_PATH` / `ICECAST_CONFIG_PATH` in `.env`).
+
+```bash
+# Clone and install
+git clone https://github.com/jerryagenyi/LANStreamer.git
+cd LANStreamer
+npm install
+
+# Configure (optional — sane defaults; needed to change admin credentials/secrets)
+cp env.example .env
+
+# Start the backend with live reload
+npm run dev
+
+# Or run the Electron desktop app on top of the backend
+npm run electron:dev
+```
+
+Then open `http://localhost:3001/dashboard` (login: `admin` / `lanstreamer123` by default — see the **Security Setup — Admin Login** section in the main [README](../README.md) for changing these).
+
+To update a source checkout later: `git pull` (work happens on `dev`, releases on `main` — see [Contributing](#-contributing)) followed by `npm install` if dependencies changed.
+
+### 📜 npm Scripts
+
+| Script | Purpose |
+|--------|---------|
+| `npm start` | Run the backend server (`src/server.js`) |
+| `npm run dev` | Backend with nodemon auto-restart |
+| `npm run electron:dev` | Launch the Electron desktop app (`electron/main.js`) |
+| `npm run electron:smoke` | Electron smoke test — boots the app, waits for load, prints `SMOKE_OK`, exits |
+| `npm run electron:build:win` | Build the Windows installer + portable package (`release/`, via electron-builder; runs `scripts/prepare-telemetry-key.mjs` first) |
+| `npm test` | Run the Jest test suite |
+| `npm run test:coverage` | Jest with coverage report |
+| `npm run build:css` | Rebuild the Tailwind bundle (`public/assets/vendor/tailwind.css`) — run after any class/token change |
+| `npm run vendor:fonts` | Self-host font files into `public/assets/vendor/fonts` |
+| `npm run setup` | First-time setup helper (`scripts/setup.js`) |
+| `npm run screenshots` | Generate the screenshot suite (`scripts/generate-screenshots.js`) |
+
+---
+
+## 📁 Project Structure
+
+```
+LANStreamer/
+├── electron/ # Desktop app shell (main.js: window, tray, lifecycle)
+├── src/ # Backend (Node.js/Express)
+│ ├── app.js # Express app + page routes (/dashboard, /streams, /docs, /login)
+│ ├── server.js # Standalone server entry (npm start)
+│ ├── routes/ # API + system routes
+│ ├── services/ # StreamingService, IcecastService, TelemetryService, ...
+│ └── utils/ # errorDiagnostics and friends
+├── public/ # Frontend (dashboard, listener page, docs page)
+│ ├── assets/css|js/ # Design tokens, shared UI CSS, shared JS (toasts, QR share, ...)
+│ ├── assets/vendor/ # Self-hosted Tailwind build + fonts (no runtime CDNs)
+│ └── components/ # Frontend components (FFmpegStreamsManager, ...)
+├── tests/ # Jest suite (unit/ integration/ scenarios/ + fixtures/)
+├── scripts/ # Verification, diagnostics, build helpers
+├── config/ # Runtime config, auto-generated (streams.json, icecast.xml, telemetry.json, ...)
+├── docs/ # Documentation (this file lives here)
+├── manual-setup/ # Hardware-specific setup guides
+├── Start LANStreamer Server.bat # Windows one-click start from a source/ZIP copy
+└── Update LANStreamer.bat # Windows update script for ZIP installs
+```
+
+---
+
+## 🏗️ Architecture Notes
+
+LANStreamer orchestrates three core components:
+
+1. **Audio Input** — any detected audio device (microphone, audio interface, virtual audio cable)
+2. **FFmpeg** — reads audio channels, encodes, and pushes to the streaming server
+3. **Icecast** — open-source streaming server that broadcasts to network clients
+
+Key modules:
+
+- `src/services/StreamingService.js` — core FFmpeg process management (spawn, port detection, exit-code handling)
+- `src/services/IcecastService.js` — Icecast integration (start/stop, config generation, LAN host detection)
+- `src/utils/errorDiagnostics.js` — error pattern matching → user-friendly messages (first-match-wins order is load-bearing)
+- `electron/main.js` — desktop shell: runs the Express server **in-process**, opens the dashboard window, hides to tray on window close (streams keep running for listeners), tree-kills FFmpeg/Icecast on quit, port fallback (3001 → 3002 …) if the port is busy, first-run telemetry consent dialog
+
+Deep dives: [APP-FLOW.md](APP-FLOW.md) (every page, user flow, and component) and [LATENCY.md](LATENCY.md) (how listener audio delay was cut from 4–5 s to ~1 s: the MSE low-latency player, Icecast's ½-second delivery tick, the FFmpeg/proxy tuning, and the measured numbers). [CLAUDE.md](../CLAUDE.md) holds the enforced patterns and UI rules you must follow when changing code.
+
+---
+
+## ⚙️ System Requirements (Development)
+
+- **Node.js 18+** (the packaged desktop app drops this requirement for end users)
+- **FFmpeg + Icecast** installed separately for now (bundling is planned); see [Installation Guides](guides/README.md)
+- **OS:** develop on Windows/macOS/Linux — the web UI and Electron app are cross-platform, though audio device naming (DirectShow on Windows) differs
+- **CI** (`.github/workflows/ci.yml`): runs on every push/PR to `main` and `dev`, on `ubuntu-latest` with Icecast installed — executes the design-token integrity check (`scripts/check-design-tokens.mjs`) and the full Jest suite (`npm test`). Branch protection requires green CI before merge.
+
+---
+
+## 🧪 Testing
+
+### Automated suite (Jest)
+
+```bash
+npm test # run everything
+npm run test:coverage # with coverage report
+```
+
+Jest runs with `--experimental-vm-modules` (the project is ESM — `"type": "module"`). Test layout:
+
+| Folder | Contents |
+|--------|----------|
+| `tests/unit/` | `StreamingService`, `IcecastService`, `errorDiagnostics` unit tests |
+| `tests/integration/` | Server startup, auth, admin-localhost lock, telemetry client relay, stream create/start/reorder/proxy, start-all, spawn errors |
+| `tests/scenarios/` | Error-scenario coverage |
+| `tests/fixtures/` | Shared fixtures (`tests/setup.js` is the global setup) |
+
+**Integration-test rule:** mock `StreamingService` (see `auth.test.js` / `telemetry-client.test.js`) — importing the real one spawns ffmpeg/icecast during module load and the worker hangs forever. To test the real auth gate, `delete process.env.AUTH_DISABLED` at the top of the file like those suites do.
+
+### Electron smoke test
+
+```bash
+npm run electron:smoke # boots the real app, waits for dashboard load, prints SMOKE_OK, exits 0
+```
+
+### Verification & diagnostic scripts (`scripts/`)
+
+Puppeteer-driven checks against the live app (start the server first) — each was built to verify a specific fix round:
+
+- `verify-auth.mjs` — admin login gate (wrong/right credentials, token storage, authed calls, public listener surface)
+- `verify-conflict.mjs` — the canonical E2E: device-conflict busy error, edit-frees-device, blocked stream then starts; asserts ZERO orphaned ffmpeg afterwards
+- `verify-chplay.mjs`, `verify-banner.mjs` — listener channel-row play button; event-banner cover + lightbox
+- `verify-flat.mjs`, `verify-header.mjs` — flat cards (no shadow/hover/animation) and sticky-header layering (toasts/menus above the bar, opaque bg)
+- `verify-sticky-scroll.mjs` — BEHAVIORAL sticky check (computed-style checks pass even when sticky is dead): scrolls both pages, asserts header `top === 0` and no horizontal overflow
+- `verify-host.mjs`, `verify-offline.mjs` — LAN-IP detection overrides stale saved hosts; app renders with ALL non-localhost requests aborted (offline proof)
+- `verify-client-telemetry.mjs` — listener failure relay E2E: real browser error → POST /api/telemetry/client-event → PostHog queue (sends past flushAt so events land in Live). Run against a fresh server (`PORT=3010 node src/server.js` + `BASE_URL=http://localhost:3010`) when the user's Electron app owns 3001
+- `verify-latency.mjs` — the latency proof: MSE player buffered-ahead (~0.5 s steady) vs plain-src baseline (~2.3 s), time-to-first-audio, and the pause→resume snap-back-to-live cycle. **Invariant: listener playback goes through `setAudioSource()`** (`streams.html`) — MSE path via `LSLowLatency` (`assets/js/lowlatency.js`, currently v=3; buffer target 0.75s — do NOT go below ~0.6s, Icecast delivers in 500ms ticks) with plain-src fallback for Safari/iOS or MSE failure; never assign `audioPlayer.src = proxyUrl` directly, or the browser's default prebuffering (the "4–5 seconds" report) returns
+- `prepare-telemetry-key.mjs` — bundles the PostHog key (env or `~/.secrets/posthog`) into gitignored `electron/telemetry-key.json` so packaged/distributed installs report after their first-run consent prompt
+- `verify-lightselect.mjs`, `verify-rowalign.mjs` — light-mode dropdown contrast; stream-row action icons pinned in a fixed RIGHT column (stable right edge across rows and live→stopped flips; ⋯ popup opens leftward inside the card)
+- `verify-fixes.mjs`, `verify-p2p3.mjs`, `verify-p4.mjs`, `verify-round3.mjs` — earlier redesign/fix rounds
+- `diag-listener.mjs`, `diag-toggle.mjs`, `diag-processes.ps1` — console/network forensics on the listener page, collapse-toggle timing, and stray FFmpeg/Icecast process inspection
+- `check-design-tokens.mjs` — the CI-enforced UI integrity linter (see below)
+
+Also in `scripts/`: `setup.js` (first-run setup), `generate-screenshots.js` / `generate-screenshot-suite.mjs` (screenshot suite), `stitch-screenshot-pdf.py`, `vendor-fonts.mjs`, `prepare-telemetry-key.mjs` (build step for the Windows package).
+
+The manual pre-release test pass lives in [GO-LIVE-CHECKLIST.md](./GO-LIVE-CHECKLIST.md) (the old manual TEST-PLAN is archived).
+
+---
+
+## 🎨 UI Rules & Integrity Linter (CI-enforced)
+
+- **Design tokens are the single source of truth** (`public/assets/css/tokens.css`); Tailwind maps them to semantic classes. Never hardcode hex colors or dark-only grays in new UI code.
+- **Shared components live in `public/assets/css/ui.css`** — new variants need a shared definition there first.
+- **Toasts stack** via `LSToasts.show(...)`; never hand-roll `position:fixed` toasts. Never use `alert()`.
+- **No runtime CDN dependencies** — fonts/icons/styles are self-hosted (`npm run vendor:fonts`, `npm run build:css`). `verify-offline.mjs` enforces this.
+- **Sharing the listener page happens in ONE place** (header share card with open/copy/QR via `LSShare`) — never per-stream share buttons.
+- **Flat surfaces (2026-10-29, explicit owner rule):** cards get NO hover effects, NO shadows, NO animations; collapse chevrons snap. The ONLY shadowed surface is the sticky header (`0 2px 8px rgba(0,0,0,.15)`). Status indicators (LIVE pip, eq bars, boot dots) and button accents are controls and keep their motion.
+- **Z-index ladder (keep to it):** menu-pop/bell panel 120 · scrim 130 · drawer 140 · lightbox 150 · **toasts 200** · boot overlay 9999 — everything above the sticky header (100). Anything below 100 will be hidden behind the header.
+- **`position: sticky` dies silently** in TWO ways — and `getComputedStyle(el).position === 'sticky'` proves NEITHER: (1) any ancestor with `overflow: hidden/auto/scroll` becomes the containing block instead of the page; (2) the sticky element's parent is only as tall as the element itself (e.g. a flex item like `#header-container`) — zero slack, nothing to stick within. Fix (2) by making the parent sticky (`#header-container{position:sticky;top:0}` in ui.css). Always verify BEHAVIORALLY — scroll the page and assert the header's `getBoundingClientRect().top === 0` (`scripts/verify-sticky-scroll.mjs`).
+- **Buttons cannot nest.** A `` inside a `` gets ejected by the HTML parser (icons fly out of rows). Use `span[role=button]` + `stopPropagation` for controls inside a toggle (see the Audio-inputs rescan in `public/index.html`).
+- **Bust the asset cache on every change:** all local CSS/JS includes carry `?v=N` per page — bump it on every page whenever that asset changes, or open tabs serve stale code mixed with new markup (has caused multiple false bug reports).
+- `node scripts/check-design-tokens.mjs` fails CI on **new** violations; existing debt is grandfathered in `scripts/design-token-baseline.json` (update deliberately with `--update-baseline` and say why in the commit).
+- Component showcase (dev-only) at `/showcase.html` — new UI must match a pattern shown there.
+
+The full, current rules are in [CLAUDE.md](../CLAUDE.md) — read them before touching UI.
+
+---
+
+## 📊 Telemetry Implementation (PostHog)
+
+- `src/services/TelemetryService.js` — **opt-in only**; sends nothing unless (a) the user consented (first-run Electron prompt; toggle in the tray menu) **and** (b) `POSTHOG_KEY` is set in the environment (`POSTHOG_HOST` optional). No-op otherwise — keep it that way for any new events.
+- Events: `app_start`, `stream_started` (format), `stream_stopped`, `stream_failed` (error *category* only), `telemetry_enabled`/`telemetry_disabled`. Every event carries a fixed `app: lanstreamer` tag (the maintainer's PostHog project is shared across apps).
+- **Never** capture personal data, audio, stream names, or file paths. Distinct ID = anonymous install UUID stored in `config/telemetry.json`.
+- Skipped entirely under `NODE_ENV=test`. All calls are fire-and-forget with `catch` — telemetry must never break the app.
+- Consent prompt lives in `electron/main.js` (`maybeAskTelemetryConsent`); the build injects the key via `scripts/prepare-telemetry-key.mjs`.
+- User-facing wording lives in the **Telemetry & Privacy** section of the main [README](../README.md) — keep the two in sync when changing what is collected.
+
+---
+
+## 🤝 Contributing
+
+**Branch workflow (do not bypass):**
+
+- `main` is the stable release branch — **never commit to main directly**. It is PR-protected: `enforce-prs.yml` auto-reverts any main commit that wasn't merged via a PR with green CI.
+- `dev` is the integration branch — all changes land here before main.
+- Flow: `main` → create `feature/xyz` → work → merge feature into `dev` locally → `npm test` → push `dev` → merge `dev` → PR → `main` (release).
+
+**Pre-review gate for streaming features:** every PR that adds or changes streaming behavior (stream lifecycle, proxying, device capture, listener fanout, start-all, queueing) must answer the 7 hostile conditions in [pressure-checklist.md](pressure-checklist.md) in the PR description for the changed code path.
+
+**Before submitting:** run `npm test`, and `npm run build:css` if you touched any classes. For bug reports, include your OS, Node.js version, and steps to reproduce.
+
+---
+
+## 🛠️ Developer Troubleshooting & Gotchas
+
+- **Startup order:** Icecast must be running before streams are created (the app auto-starts it; keep the order if you refactor).
+- **Icecast source limit:** Icecast defaults to 2 concurrent streams — raise `` in the generated `config/icecast.xml` when testing many streams.
+- **Windows FFmpeg exit codes are unsigned** and need conversion to signed (e.g. `0xA7F00008`) — handled in `StreamingService.js`; don't remove.
+- **DirectShow device names:** Windows requires device name mapping when spawning FFmpeg.
+- **Logs:** `logs/combined.log` (winston, daily rotation) is the first place to look when a stream fails silently.
+- **Port detection:** Icecast port is auto-detected from config, default 8000.
+- **Zombie processes:** on Windows, killing the server does not kill FFmpeg/Icecast children — the Electron shell tree-kills them (`taskkill /T /F`); when testing from source, check Task Manager or run `scripts/diag-processes.ps1`.
+- **Kill order invariant:** `killProcessTree` must run `taskkill /PID /T /F` BEFORE any `.kill()` on the child — a lone SIGTERM only ends the `cmd.exe` wrapper (streams spawn with `shell:true`) and orphans FFmpeg holding the audio device exclusively. Every path that stops a stream (stop, restart-failure, update, delete) must go through `killProcessTree`, never a bare `.kill()`. `verify-conflict.mjs` asserts zero orphans after its run.
+- **Startup is owned by the Electron shell** (`electron/main.js`: port fallback, orphan sweep, ordered teardown). The old server-only boot sequence doc is archived.
+
+---
+
+## 📚 Developer Documentation
+
+| Document | Description |
+|----------|-------------|
+| [GO-LIVE-CHECKLIST.md](GO-LIVE-CHECKLIST.md) | Pre-release checklist — test matrix, packaging, security blockers, release process |
+| [APP-FLOW.md](APP-FLOW.md) | Every page, user flow (mermaid), wireframe, and component |
+| [pressure-checklist.md](pressure-checklist.md) | Pre-review gate for streaming PRs |
+| [TROUBLESHOOTING.md](TROUBLESHOOTING.md) | Deep troubleshooting (network, firewall, Icecast, playback) |
+| [CLAUDE.md](../CLAUDE.md) | Enforced patterns, UI rules, and contribution workflow |
+| [archive/](./archive/) | Superseded docs (pre-Electron architecture, shipped plans) — indexed, not current |
+| [docs index](README.md) | Full documentation index |
+
+---
+
+**LANStreamer** — developer documentation. For usage, installation, and the listener experience, see the main [README](../README.md).
diff --git a/docs/README.md b/docs/README.md
index b7e916f..1bee8b6 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,127 +1,40 @@
# LANStreamer Documentation
-This directory contains comprehensive documentation for the LANStreamer project.
-
-## 📚 Documentation Index
-
-### Core Documentation
-
-| Document | Description | Audience |
-|----------|-------------|----------|
-| **[LANSTREAMER_SYSTEM_ARCHITECTURE.md](./LANSTREAMER_SYSTEM_ARCHITECTURE.md)** | ⭐ **Complete system architecture** - Detailed technical documentation covering all services, startup sequence, configuration, and troubleshooting | Developers, AI assistants, advanced users |
-| **[TROUBLESHOOTING.md](./TROUBLESHOOTING.md)** | Common issues and solutions - Practical troubleshooting guide for real-world problems | All users |
-| **[NETWORK-SETUP.md](./NETWORK-SETUP.md)** | Network configuration guide - Static IP setup for events and conferences | Event organisers, network admins |
-| **[CHANGELOG.md](./CHANGELOG.md)** | Version history - Release notes, updates, and compatibility information | All users |
-
-### Installation Guides
-
-| Guide | Description |
-|-------|-------------|
-| **[guides/README.md](./guides/README.md)** | Installation guides index |
-| **[guides/ffmpeg-installation.md](./guides/ffmpeg-installation.md)** | FFmpeg installation and setup |
-| **[guides/icecast-installation.md](./guides/icecast-installation.md)** | Icecast server installation |
-| **[guides/audio-pipeline-simple.md](./guides/audio-pipeline-simple.md)** | Simple audio pipeline setup |
-
-### Archived Documentation
-
-Old documentation files are preserved in the `archive/` folder for reference:
-- `archive/ARCHIVED_ICECAST_CONFIGURATION_AND_RUNTIME_ARCHITECTURE.md` - Previous Icecast-focused architecture doc (content merged into SYSTEM_ARCHITECTURE.md)
-
----
-
-## 🚀 Quick Start
-
-1. **Install dependencies:** `npm install`
-2. **Configure environment:** Copy `.env.example` to `.env` and modify as needed
-3. **Start development server:**
- - **With live reload:** `npm run dev:live` → `http://localhost:3002` ⚡
- - **Regular mode:** `npm run dev` → `http://localhost:3001`
-4. **Access dashboard:** Add `/dashboard` to either URL
-
-### 🔄 Development Mode
-
-For the best development experience, use `npm run dev:live`:
-- **Auto-refresh** on file changes (no more manual refresh!)
-- **BrowserSync** dashboard for development tools
-- **Multi-device testing** support
-- **Network access** for testing on other devices
-
----
-
-## 📖 Documentation Structure
-
+LANStreamer is an **Electron desktop app in active development** — most people will install the packaged app; it also runs straight from this repo for contributors and source users. Documentation below is split the same way. Current status: no installer released yet — see the status block in the [main README](../README.md).
+
+## 📦 Using the app
+
+| Document | Description |
+|----------|-------------|
+| **[../README.md](../README.md)** | Start here — quick start (desktop app or source), admin login, telemetry & privacy |
+| **[TROUBLESHOOTING.md](./TROUBLESHOOTING.md)** | Common issues — subnet, firewall, playback (plus the in-app guide at `/docs`) |
+| **[NETWORK-SETUP.md](./NETWORK-SETUP.md)** | Static-IP setup for events and conferences |
+| **[LATENCY.md](./LATENCY.md)** | Where audio delay comes from and how to cut it |
+| **[CHANGELOG.md](./CHANGELOG.md)** | Version history and release notes |
+| **[manual-setup/](../manual-setup/)** | Hardware-specific guides (Behringer DVS, XR18, and friends) |
+| **[guides/](./guides/)** | FFmpeg / Icecast installation — **packaged app: not needed (binaries are bundled)**; source/server-only installs: required |
+
+## 🛠️ Developing & running from source
+
+| Document | Description |
+|----------|-------------|
+| **[README-DEVELOPERS.md](./README-DEVELOPERS.md)** | ⭐ Start here — dev loop (`electron:dev`), tests, architecture notes, UI rules, telemetry internals |
+| **[GO-LIVE-CHECKLIST.md](./GO-LIVE-CHECKLIST.md)** | Pre-release checklist — test matrix, packaging, security blockers, GitHub release process |
+| **[APP-FLOW.md](./APP-FLOW.md)** | Every page, user flow (mermaid), and component — the UI map |
+| **[pressure-checklist.md](./pressure-checklist.md)** | PR review gate for streaming-behavior changes |
+| **[UX-AUDIT-2026-10.md](./UX-AUDIT-2026-10.md)** | Holistic UX assessment (IxDF framework) — scores, prioritized issues, redesign roadmap |
+| **[benchmark-report-v1.md](./benchmark-report-v1.md)** | Performance baseline (kept current until the latency round lands v2) |
+| **[../CLAUDE.md](../CLAUDE.md)** | Code conventions for AI-assisted contributors |
+
+```bash
+npm install # dependencies
+npm run electron:dev # the DESKTOP APP (what users run)
+npm run dev # server-only (no Electron shell) → http://localhost:3001
+npm test # Jest suite
```
-docs/
-├── README.md # This file - documentation index
-├── LANSTREAMER_SYSTEM_ARCHITECTURE.md # ⭐ Core architecture documentation
-├── TROUBLESHOOTING.md # Practical troubleshooting guide
-├── NETWORK-SETUP.md # Network configuration guide
-├── CHANGELOG.md # Version history
-├── guides/ # Installation guides
-│ ├── README.md # Guides index
-│ ├── ffmpeg-installation.md
-│ ├── icecast-installation.md
-│ └── audio-pipeline-simple.md
-└── archive/ # Archived documentation
- └── ARCHIVED_ICECAST_CONFIGURATION_AND_RUNTIME_ARCHITECTURE.md
-```
-
----
-
-## 🎯 Finding What You Need
-
-### For Users
-- **Getting started?** → See main [README.md](../README.md)
-- **Having problems?** → Start with [TROUBLESHOOTING.md](./TROUBLESHOOTING.md)
-- **Setting up network?** → See [NETWORK-SETUP.md](./NETWORK-SETUP.md)
-- **Installing components?** → See [guides/](./guides/)
-
-### For Developers
-- **Understanding the system?** → Read [LANSTREAMER_SYSTEM_ARCHITECTURE.md](./LANSTREAMER_SYSTEM_ARCHITECTURE.md)
-- **Contributing code?** → See [CLAUDE.md](../CLAUDE.md) for development workflow
-- **API reference?** → See architecture doc Section 5 (Stream Creation Flow)
-
-### For AI Assistants
-- **System architecture?** → [LANSTREAMER_SYSTEM_ARCHITECTURE.md](./LANSTREAMER_SYSTEM_ARCHITECTURE.md) contains complete technical details
-- **Error diagnostics?** → Architecture doc Section 6 (Error Handling & Diagnostics)
-- **Service interactions?** → Architecture doc Section 3 (Core Services)
-
----
-
-## 🔍 Quick Reference
-
-### Common Tasks
-
-| Task | Document | Section |
-|------|----------|---------|
-| Understand system architecture | SYSTEM_ARCHITECTURE.md | Section 1: System Overview |
-| Trace stream creation flow | SYSTEM_ARCHITECTURE.md | Section 5: Stream Creation Flow |
-| Debug connection issues | TROUBLESHOOTING.md | Icecast Connection Issues |
-| Configure static IP | NETWORK-SETUP.md | Full guide |
-| Install FFmpeg | guides/ffmpeg-installation.md | Full guide |
-| Install Icecast | guides/icecast-installation.md | Full guide |
-
----
-
-## 📝 Documentation Standards
-
-- **Architecture docs** include file names, line numbers, and function names for precision
-- **Troubleshooting guides** include step-by-step solutions with commands
-- **Installation guides** are platform-specific with screenshots where helpful
-- **All docs** are kept up-to-date with codebase changes
-
----
-
-## 🤝 Contributing to Documentation
-When updating documentation:
-1. Keep technical accuracy - verify file paths and line numbers
-2. Update cross-references if moving content
-3. Test all commands and examples
-4. Follow the existing structure and formatting
-5. Update this README if adding new documents
+Dashboard login: `admin` / `lanstreamer123` by default (README → Security Setup).
----
+## 🗄️ Archive
-**Last Updated:** 2026-01-27
-**Documentation Version:** Aligned with codebase v1.2.3
+Superseded docs (pre-Electron architecture, shipped redesign plans, old test plans) live in **[archive/](./archive/)** with an index stating what replaced each one.
diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md
index 5e94de3..88bc926 100644
--- a/docs/TROUBLESHOOTING.md
+++ b/docs/TROUBLESHOOTING.md
@@ -13,6 +13,29 @@ Common issues and solutions for LANStreamer.
---
+## Stale streams after tool upgrades or network changes
+
+**Symptom:** a stream that worked before won't start; the dashboard shows a red "Cannot connect to Icecast" error; creating a new stream also fails.
+
+**Cause:** Icecast isn't running (common after upgrading/moving the Icecast install, a reboot, or a network change). Streams need a live Icecast to push into.
+
+**Fix (automatic since 2026-10-28):** starting a stream now **auto-starts Icecast** if it is installed and not running — normally you never see this. If it still fails:
+
+1. Check the Icecast panel on the dashboard — does the path/version look right? After moving or upgrading Icecast, click **Search Installations** (or delete `config/device-config.json` and restart) so the app re-detects it.
+2. Networks that use DHCP change the machine's IP; LANStreamer polls Icecast over `localhost` (immune to IP changes) and auto-syncs the hostname in `icecast.xml`. No manual step needed.
+
+**Do you need to delete and recreate the stream?** No — streams persist their device + settings and start fine once Icecast is reachable. Only recreate if the audio device itself no longer exists.
+
+## Audio devices listed twice (or missing) after a FFmpeg upgrade
+
+**Symptom:** every device appears twice in the dropdown, or only odd "ps-*" devices appear.
+
+**Cause:** FFmpeg 9 changed its device-listing output format (`[dshow @ …]` became `[in#0 @ …]`), which older LANStreamer versions could not parse — they fell back to PowerShell discovery, which lists each device as both input and output.
+
+**Fix (automatic since 2026-10-28):** the parsers accept both formats and results are de-duplicated. Click **Refresh Devices** once after upgrading FFmpeg. If duplicates persist, restart the server.
+
+---
+
## Admin only on localhost
Admin (login, dashboard, stream management) is **only available from this computer** (localhost).
@@ -499,7 +522,7 @@ When troubleshooting, check these in order:
## Still Having Issues?
-1. Check the [System Architecture Documentation](LANSTREAMER_SYSTEM_ARCHITECTURE.md) for detailed technical information
+1. Check the [developer guide](README-DEVELOPERS.md) for architecture notes and the diagnostic script inventory
2. Review [Network Setup Guide](NETWORK-SETUP.md) for network configuration
3. Check [Installation Guides](guides/README.md) for component setup
4. Create an issue on GitHub with:
diff --git a/docs/UI-UX-RECOMMENDATIONS.md b/docs/UI-UX-RECOMMENDATIONS.md
deleted file mode 100644
index ef28ed6..0000000
--- a/docs/UI-UX-RECOMMENDATIONS.md
+++ /dev/null
@@ -1,189 +0,0 @@
-# UI/UX Recommendations for LANStreamer Dashboard
-
-Suggestions for modernising the admin dashboard (e.g. [localhost:3001](http://localhost:3001/)). Implement after stability items in [TODO.md](../TODO.md) are done.
-
----
-
-## Current state
-
-The dashboard has a solid dark theme. Action buttons in the Audio Streams section (Refresh Devices, Stop All, Start New Stream) could use clearer hierarchy and more consistent, modern styling.
-
----
-
-## 1. Action button modernisation
-
-**Issues:** Flat buttons, inconsistent visual weight, limited iconography; "Stop All" and future "Start All" don’t stand out enough.
-
-**Suggestions:**
-
-```css
-/* Primary actions – rounded, elevated */
-.primary-action-btn {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border-radius: 12px;
- padding: 12px 24px;
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
- transition: all 0.3s ease;
-}
-
-.primary-action-btn:hover {
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
-}
-
-/* Success/Start */
-.success-action-btn {
- background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
- border-radius: 12px;
-}
-
-/* Danger/Stop */
-.danger-action-btn {
- background: linear-gradient(135deg, #eb3349 0%, #f45c43 100%);
- border-radius: 12px;
-}
-
-/* Secondary */
-.secondary-action-btn {
- background: rgba(255, 255, 255, 0.05);
- border: 1px solid rgba(255, 255, 255, 0.1);
- border-radius: 10px;
- backdrop-filter: blur(10px);
-}
-```
-
----
-
-## 2. Icons
-
-- Consider **Lucide Icons** or **Heroicons** instead of Material Icons for consistency.
-- Use 20–24px for better visibility; add subtle hover animation.
-- **Start New Stream:** play circle or + in circle.
-- **Stop All:** stop/pause with warning colour.
-- **Start All:** stacked play or fast-forward.
-- **Refresh Devices:** rotating arrow with spin on click.
-- **Live:** pulsing dot instead of static.
-
----
-
-## 3. Button layout
-
-Group actions with clear hierarchy and spacing, e.g.:
-
-- Section: “Audio Streams” with “4/4 Live” badge (animated).
-- Row: [Refresh] [Start All] [Stop All], then [Start New Stream] as primary.
-
----
-
-## 4. Status badge (“4/4 Live”)
-
-- Larger, more prominent.
-- Pulsing animation for active streams.
-- Optional: gradient + glass effect.
-
-```css
-.live-badge {
- background: rgba(56, 239, 125, 0.15);
- border: 2px solid rgba(56, 239, 125, 0.5);
- border-radius: 20px;
- padding: 8px 16px;
- backdrop-filter: blur(10px);
- animation: pulse 2s ease-in-out infinite;
-}
-
-@keyframes pulse {
- 0%, 100% { opacity: 1; }
- 50% { opacity: 0.7; }
-}
-```
-
----
-
-## 5. Stream cards
-
-- Border-radius 12–16px.
-- Subtle hover elevation and separation between cards.
-- Optional glass-morphism.
-
----
-
-## 6. Page layout
-
-- **Header:** More padding; optional glass bar; logo with subtle emphasis.
-- **Security warning:** Clearer treatment, optional dismiss; amber/orange.
-- **Server status:** Animated “online” indicator; card style; colour-coded controls.
-
----
-
-## 7. Responsive button group (markup)
-
-```html
-
-
- ...
- Refresh Devices
-
-
- ...
- Start All
-
-
- ...
- Stop All
-
-
- ...
- Start New Stream
-
-
-```
-
----
-
-## 8. Animation and micro-interactions
-
-- Button hover: slight lift and glow.
-- Live indicators: pulse.
-- Uptime: smooth value updates.
-- Loading: skeleton or shimmer.
-- Success: short confirmation feedback.
-
----
-
-## 9. Colour palette (CSS variables)
-
-```css
-:root {
- --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- --success-gradient: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
- --danger-gradient: linear-gradient(135deg, #eb3349 0%, #f45c43 100%);
- --warning-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
-
- --glass-bg: rgba(255, 255, 255, 0.05);
- --glass-border: rgba(255, 255, 255, 0.1);
-
- --shadow-soft: 0 2px 8px rgba(0, 0, 0, 0.1);
- --shadow-medium: 0 4px 16px rgba(0, 0, 0, 0.2);
- --shadow-large: 0 8px 32px rgba(0, 0, 0, 0.3);
-}
-```
-
----
-
-## 10. Accessibility
-
-- Buttons: min-height 44px for touch.
-- Clear focus outlines.
-- Sufficient contrast (WCAG).
-- ARIA labels for icon-only buttons.
-- Keyboard navigation.
-
----
-
-## Implementation priority
-
-1. **High:** Button styling and icons.
-2. **Medium:** Glass effects, animations.
-3. **Low:** Advanced micro-interactions.
-
-Focus on stability and feature completeness (see [TODO.md](../TODO.md)) before deep UI polish.
diff --git a/docs/UX-AUDIT-2026-10.md b/docs/UX-AUDIT-2026-10.md
new file mode 100644
index 0000000..3585ea3
--- /dev/null
+++ b/docs/UX-AUDIT-2026-10.md
@@ -0,0 +1,75 @@
+# UX Audit — LANStreamer (2026-10-30)
+
+Holistic assessment using the IxDF framework (7 UX factors · 5 usability characteristics · 5 interaction dimensions). Evidence: fresh screenshots of all surfaces (this file's sibling evidence in `screenshots/ux-*.png`), a year of operator feedback (Jerry's rounds), and the shipped 2026-10 redesign. Audited state: dev tip `a2fa9f8`.
+
+**Personas** (from actual usage): **Jerry-operator** — sets up streams at events, semi-technical, wants zero babysitting mid-event. **Event listener** — congregation/meeting attendee, any phone, zero patience, opens a link once. **Novice operator** — gets the app from GitHub, first event next week.
+
+---
+
+## Executive summary
+
+**Overall: 68/85 — B (Good).** The redesign landed a genuinely strong operator console (status strip, classified actionable errors, forgiving listener page with auto-resume). The product's biggest UX liability is not visual — it is **time**: measured ~5 s end-to-end audio latency (user report; browser-buffer dominated) directly undermines the core same-room interpretation use case. Second: the first-run path now stacks up to four gates before the operator controls anything. Third: accessibility is untested systematically.
+
+---
+
+## 1. UX Factors (29/35)
+
+| Factor | Score | Evidence |
+|---|---|---|
+| Useful | 5 | Solves a real, otherwise-expensive problem (interpretation hardware); persistent streams, auto-start, QR sharing |
+| Usable | 4 | Core flows (add stream → go live → share) are short; icon-only controls with tooltips everywhere; ⋯ menus group row actions |
+| Findable | 4 | Status strip answers "is it working?" at a glance; share surface is one card; in-app /docs discoverable from error boxes |
+| Credible | 3.5→4* | Opt-in telemetry well disclosed; per-install credentials now minted; *the latency itself and (pending) unsigned-installer SmartScreen warning erode trust |
+| Desirable | 4 | Post-redesign token system, both themes, flat surfaces read as intentional |
+| Accessible | 3 | aria-labels on icon buttons, color-scheme per theme; but no systematic keyboard/focus/contrast pass (see issues) |
+| Valuable | 5 | Free/OSS, LAN-private, no listener install — clear value story |
+
+## 2. Usability Characteristics (20/25)
+
+| Characteristic | Score | Evidence |
+|---|---|---|
+| Effectiveness | 5 | Stream lifecycle (create/live/stop/retry/edit/duplicate/reorder) all work; conflict + error paths verified E2E repeatedly |
+| Efficiency | 4 | One-click go-live; Start All; rescan without opening the card; row actions never shift |
+| Engagement | 4 | Eq/status motion only where meaningful (and frozen on pause); boot screen resolves fast |
+| Error Tolerance | 4.5 | Best-in-class errors: classified cause + plain-language fix + inline Change input/Retry + collapsed diagnostics + /docs link. Half point off: dirty-state traps (leftover instances, device holders) still confuse — mitigated by the new port-fallback dialog + orphan sweep |
+| Ease of Learning | 3 | First-run stacks gates (login → credentials dialog → telemetry prompt → default-creds banner); concepts like "virtual audio cable" arrive unexplained outside guides |
+
+## 3. Interaction Dimensions (19/25)
+
+| Dimension | Score | Evidence |
+|---|---|---|
+| Words | 4 | Friendly, short microcopy; listener errors say what to do ("ask the operator to check it"); minor jargon residue (bitrate chips, "S1" labels) |
+| Visual | 4 | Consistent tokens, both themes verified; default event banner removes the broken-looking empty state |
+| Physical/Space | 4 | Listener mobile layout solid (mini-player, touch-sized rows); dashboard is desktop-first (acceptable — operator uses a PC) |
+| Time | 3 | **The latency lives here.** ~5 s reported (≈3–4.5 s browser buffer + encoder/icecast contributions); the fix (MSE player + FFmpeg flags + proxy tweaks) is planned and specced — see docs/LATENCY.md + the Claude latency review |
+| Behavior | 4 | Buttons respond with toasts + row state; play/pause icons reflect reality (incl. the pause-flip and eq-freeze fixes); auto-resume behavior matches user intent |
+
+---
+
+## 4. Prioritized issues
+
+| # | Severity | Issue | Where |
+|---|---|---|---|
+| 1 | **Critical** | Audio latency (~5 s → target ≤1 s) undermines the core same-room use case; users hear it as "broken" | Listener playback path |
+| 2 | High | First-run gate stack: login + show-once credentials dialog + telemetry prompt + default-creds banner before first stream | Electron shell + dashboard |
+| 3 | Medium | No systematic accessibility pass (focus order, visible focus rings, contrast ratios, keyboard-only stream start) | All surfaces |
+| 4 | Medium | Unsigned installer will trigger SmartScreen — first impression for exe users is a security warning (SHA256SUMS + notes mitigate partially) | Release |
+| 5 | Low | Dashboard on phones stacks but is cramped — operators occasionally want a status glance from their phone | Dashboard responsive |
+| 6 | Low | /docs page is long unbroken text; collapsible sections would help scanning | public/docs.html |
+
+## 5. Redesign proposals (evolution, not revolution — the 2026-10 redesign holds)
+
+1. **Latency round (P1, specced):** MSE-based listener player with ~0.3–0.5 s buffer + drift resync; FFmpeg low-delay flags; proxy `flushHeaders`/`setNoDelay`; Icecast burst 16 KB. Measure with a clap test before/after. Expected 5 s → ~1 s.
+2. **First-run sequence (P2):** replace the native-dialog stack with one in-dashboard welcome card: "1. save your admin login (shown once, copy button) → 2. telemetry choice → 3. create your first stream". Native dialogs remain the fallback.
+3. **Accessibility sweep (P3):** axe pass on both surfaces, visible focus rings (tokens already have accent), keyboard path for play/stop/add-stream, contrast audit in light theme.
+4. **Listener trust nicety (P4):** small "live" indicator pulse is already there; consider showing stream *labels* more prominently than S-numbers on the picker.
+
+## 6. Research recommendations
+
+- **Clap-test latency measurement** (planned with the latency round) — replaces anecdote with frames.
+- **One real-event observation** of a novice operator (where do they hesitate?).
+- **axe-core automated a11y** in CI (also on the go-live checklist).
+
+## 7. Roadmap fit
+
+Issue #1 is the already-planned latency round. #2 is a small Electron/dashboard round. #3 pairs with the pre-release a11y item in GO-LIVE-CHECKLIST. #4 is release hygiene (SHA256SUMS step exists). Nothing here invalidates the current design direction.
diff --git a/docs/LANSTREAMER_SYSTEM_ARCHITECTURE.md b/docs/archive/LANSTREAMER_SYSTEM_ARCHITECTURE.md
similarity index 100%
rename from docs/LANSTREAMER_SYSTEM_ARCHITECTURE.md
rename to docs/archive/LANSTREAMER_SYSTEM_ARCHITECTURE.md
diff --git a/docs/archive/README.md b/docs/archive/README.md
new file mode 100644
index 0000000..8f3ede3
--- /dev/null
+++ b/docs/archive/README.md
@@ -0,0 +1,16 @@
+# Archive — superseded documentation
+
+Historical documents kept for reference. **None of this describes the current
+app** — each line says what replaced it. Current documentation: [../README.md](../README.md).
+
+| File | What it was | Superseded by |
+|------|-------------|---------------|
+| `LANSTREAMER_SYSTEM_ARCHITECTURE.md` | Complete pre-Electron architecture (server-first app) | [../README-DEVELOPERS.md](../README-DEVELOPERS.md) + the Electron shell itself (`electron/main.js`); predates admin auth, the 2026-10 redesign, and binary bundling |
+| `STARTUP-SEQUENCE.md` | Pre-Electron boot sequence | Startup is now owned by the Electron main process (ordered teardown, port fallback, orphan sweep — see `electron/main.js`) |
+| `TEST-PLAN.md` | Early manual test plan | The Jest suite (`npm test`) + [../GO-LIVE-CHECKLIST.md](../GO-LIVE-CHECKLIST.md) + the `scripts/verify-*.mjs` inventory in the developer guide |
+| `UI-UX-RECOMMENDATIONS-2026-10.md` | Design analysis that fed the 2026-10 redesign | The redesign SHIPPED — the live token system (`public/assets/css/tokens.css`) and [../APP-FLOW.md](../APP-FLOW.md) are the current truth |
+| `REDESIGN-PLAN.md` | The shipped redesign's plan | Same — shipped 2026-10 (see [../CHANGELOG.md](../CHANGELOG.md)) |
+| `ROBUSTNESS-PLAN.md` | 2026-02 robustness plan (8 layers) | Largely implemented (kill-order, error diagnostics, persistence); open items live in [../../TODO.md](../../TODO.md) and [../GO-LIVE-CHECKLIST.md](../GO-LIVE-CHECKLIST.md) |
+| `UI-UX-RECOMMENDATIONS.md` | Earlier (pre-2026-10) UI analysis | Same as the 2026-10 version above |
+| `ARCHIVED_ICECAST_CONFIGURATION_AND_RUNTIME_ARCHITECTURE.md` | 2026-01 Icecast-focused architecture | Icecast bundling + the generated-config system (`src/utils/vendorPaths.js`) replaced the "configure Program Files icecast.xml" world |
+| `legacy-images/` | Visual history: original concept art, the pre-redesign web UI (terminal + dashboard screenshots), the 2026-10-28 design-review PDF, and the redesign-round evidence set (`screenshots/redesign-2026-10-28/`) | The current UI — fresh post-redesign screenshots belong in the main README before the first release (go-live checklist) |
diff --git a/docs/archive/REDESIGN-PLAN.md b/docs/archive/REDESIGN-PLAN.md
new file mode 100644
index 0000000..457675d
--- /dev/null
+++ b/docs/archive/REDESIGN-PLAN.md
@@ -0,0 +1,96 @@
+# LANStreamer redesign adoption plan
+
+Source: `LANStreamer-redesign/` (designer mock, 2026-10-28) — interactive HTML/CSS
+mocks (dashboard + listener) with a shared token sheet. This plan merges it into
+the shipped app WITHOUT losing the behavior we built this cycle (notification
+bell, boot screen, off-air auto-resume, error classification, stacked toasts,
+/docs, telemetry, Electron, tests).
+
+## Why this is an upgrade (per screen)
+
+Dashboard
+1. **Status strip** (On air x/7 · Listeners+peak · Icecast :port · Needs attention)
+ replaces status scattered across the header pill and collapsed sidebar cards.
+ The operator's first glance now answers "is the event healthy?"
+2. **Security banner demoted to warning** (not error-red) with a direct
+ "Change password" action — it stops competing with real stream failures.
+3. **Grouped + filterable stream list** ("On air" / "Ready", All·Live·Issues)
+ — the live row can no longer hide among seven stopped ones.
+4. **Source names truncate at the END with tooltip** — replaces the marquee;
+ listeners/operators read the distinguishing part of the name first.
+5. **Error rows are actionable inline** (cause + fix hint + "Change input" /
+ "Retry") instead of a collapsed toggle; the full diagnostic stays in a
+ details disclosure behind it (fed by our `errorShort` classification).
+6. **One play/stop + "⋯" menu** (copy link, edit, duplicate, delete) — Delete
+ is no longer one misclick from Play; Stop is a red square, unmistakable
+ vs Play.
+7. **New stream as a side drawer**: source list marks which device is already
+ in use, quality chosen by purpose (Speech 96 / Standard 128 / Music 192),
+ explicit **Save** (stopped) vs **Go live**, and an auto-start toggle
+ (maps to the existing `autoStart` config field).
+8. **Share card** (QR + LAN URL + copy) promoted to the sidebar at full size.
+9. **Audio inputs always visible** with IN USE / IDLE / MISSING per device.
+10. **Friendly empty state** with a 3-step guide.
+
+Listener
+1. **One big play + channel picker** with language badges (EN/FR/ES) — designed
+ for interpretation events, the app's actual purpose; far friendlier than a
+ list of identical rows.
+2. Help line for the two real "no sound" causes (wrong Wi-Fi, silent mode).
+3. Mobile mini-player pinned on scroll; ON AIR pill in the top bar.
+
+Design system
+- Space Grotesk + JetBrains Mono typography; warning split from danger;
+ `--onair` red reserved for the ON AIR badge; text label on every chip
+ (color never the sole signal); focus-visible rings; reduced-motion honored.
+
+## What we keep from the current build (mock lacks it)
+Notification bell + panel, boot screen + failure state, typed/linked stacked
+toasts (LSToasts), 15s off-air grace + auto-resume + last-stream memory,
+device-error classification (errorShort), /docs page, real QR endpoint,
+duplicate-source guard, collapse persistence, telemetry consent, Electron,
+71-test suite, showcase page.
+
+## Decisions (recommended, reversible)
+| Topic | Mock | Ours | Decision |
+|---|---|---|---|
+| Fonts | Google Fonts CDN | vendored Inter | **Adopt Space Grotesk + JetBrains Mono, vendored** (offline rule; extend `vendor:fonts` script) |
+| Icons | inline stroke SVGs | Material Symbols (vendored) | **Keep Material Symbols** — already offline + enforced; adopt only the brand mark |
+| Theme default | light | dark | **Keep dark default** + system preference (existing user expectation) |
+| Toasts | bottom-right, tag-replace, max 4 | top-center stack, tags, types, links | **Adopt bottom-right placement + styling; keep LSToasts engine** (types/links/bell integration) |
+| Device name overflow | end-truncate + tooltip | marquee | **Adopt end-truncate; drop marquee** |
+| Tailwind | none (pure CSS) | Tailwind + tokens | **Keep Tailwind** this pass; port the mock's component CSS into `ui.css` (ripping out Tailwind now would rewrite everything we just stabilized) |
+
+## Phases (each: build → GUI-verify both themes → tests → commit)
+
+**P1 — Token merge (small, low risk).** Port the mock's palette values
+(light+dark), warn/danger/onair split, radius+shadow scale, vendored fonts
+into `tokens.css`/`tailwind.config.js`; update `/showcase.html`; regenerate
+screenshots for the designer. Nothing structural changes yet.
+
+**P2 — Dashboard structure (large).** Status strip, security banner restyle,
+grouped+filtered list, new row anatomy (⋯ menu, red stop, end-truncated
+source), errbox with inline actions + details, empty state, share card,
+audio-inputs card (real IN USE/IDLE/MISSING chips). Bell/boot/collapsibles
+stay. Reorder keeps up/down (inside ⋯ menu) until P5.
+
+**P3 — New-stream drawer (medium).** Replaces the modal. Radio-card sources
+annotated "Used by S5" from live streams; purpose-based quality; auto-start
+toggle → existing `autoStart` field; **Save-as-stopped needs one small backend
+endpoint** (persist stream without starting; today streams only persist on a
+successful start).
+
+**P4 — Listener page (medium-large).** Hero + big play + channel picker +
+help line + scroll-pinned mini-player + ON AIR pill, with ALL current
+playback logic ported onto it (grace, auto-resume, last-stream, toasts, boot,
+play-failure notices).
+
+**P5 — Polish (optional).** Drag-handle reorder (keep keyboard fallback),
+listener peak tracking (session localStorage), real input level meters
+(requires an FFmpeg per-device probe — skip rather than show fake levels).
+
+## Explicitly not adopted
+- Google Fonts CDN links (offline rule) — vendored instead.
+- Decorative QR in the mock (we keep the real `/api/system/qr`).
+- Fake level-meter widths (either real backend probe in P5 or omitted).
+- Pure-CSS rewrite / Tailwind removal (revisit after P4 if desired).
diff --git a/docs/archive/ROBUSTNESS-PLAN.md b/docs/archive/ROBUSTNESS-PLAN.md
new file mode 100644
index 0000000..442dd4d
--- /dev/null
+++ b/docs/archive/ROBUSTNESS-PLAN.md
@@ -0,0 +1,319 @@
+# LANStreamer robustness plan
+
+Breaking the system down by domain with explicit failure-mode analysis. Each layer has clear boundaries, enumerated failure modes, and testable mitigation.
+
+---
+
+## Layer 1: Environment detection & setup
+
+### 1.1 Icecast discovery
+
+- **What could go wrong?**
+ - Not installed
+ - Installed but not in PATH
+ - Installed but wrong version (flags changed)
+ - Multiple versions on system
+ - Config file missing or corrupted
+ - Port conflicts (8000 already in use)
+ - Permissions issues (can't write to config/logs)
+- **How do you test for it?**
+ - `which icecast` / `where icecast`
+ - `icecast --version` and parse output
+ - Try to load/warm-start the config and catch errors
+ - Check port availability before starting
+- **Mitigation**
+ - Clear error messages with install links
+ - Prompt to download missing binary
+ - Auto-generate config from template
+ - Offer alternative port if 8000 taken
+ - Validate config before launching
+
+### 1.2 FFmpeg discovery
+
+- **What could go wrong?**
+ - Not installed
+ - In PATH but lacking codecs (libmp3lame, libopus, etc.)
+ - Wrong version (some flag changes between versions)
+ - FFmpeg exists but ffprobe doesn't (or vice versa)
+- **How do you test for it?**
+ - `ffmpeg -version` and parse for codecs
+ - `ffprobe -version` for metadata capabilities
+ - Try a dummy encode to verify codec support
+- **Mitigation**
+ - Codec-specific error messages ("You need FFmpeg with libmp3lame")
+ - Offer bundled/config instructions for common OSs
+ - Graceful degradation if some codecs missing
+
+### 1.3 Audio device discovery
+
+- **What could go wrong?**
+ - No audio devices found
+ - Device name has special characters that break CLI
+ - Device disconnected mid-stream
+ - Device name changes between sessions (Windows "Microphone (2)" vs "Microphone (3)")
+ - Permission denied (macOS/Windows privacy controls)
+- **How do you test for it?**
+ - `ffmpeg -list_devices true -f dshow -i dummy` (Windows)
+ - `ffmpeg -f avfoundation -list_devices true -i ""` (macOS)
+ - `pactl list sources` (Linux PulseAudio)
+ - Store device fingerprint/hash to detect renaming
+- **Mitigation**
+ - Cache device mappings with stable IDs
+ - Device aliasing/user-friendly names
+ - Graceful reconnection attempts
+ - Clear permission prompts
+
+---
+
+## Layer 2: Stream lifecycle management
+
+### 2.1 Stream creation
+
+- **What could go wrong?**
+ - Duplicate stream name
+ - Invalid characters in stream name (Icecast mount point restrictions)
+ - Source limit reached (Icecast default: 2 sources)
+ - Port collision if assigning unique ports per stream
+- **Testing & mitigation**
+ - Validate name against regex before creating
+ - Check Icecast `` limit before creating
+ - Pre-flight checks: "Can this stream actually start?"
+
+### 2.2 Stream start (spawn FFmpeg)
+
+- **What could go wrong?**
+ - FFmpeg exits immediately (codec issue, device busy)
+ - FFmpeg starts but no audio (silent stream)
+ - FFmpeg starts but wrong sample rate/channels
+ - Icecast rejects the connection (wrong password, mount exists)
+- **Testing & mitigation**
+ - Health check: verify FFmpeg process stays alive > 5 seconds
+ - Probe Icecast mount point to confirm audio is flowing
+ - Parse FFmpeg stderr for known error patterns
+ - Exponential backoff on retry
+
+### 2.3 Stream stop/cleanup
+
+- **What could go wrong?**
+ - FFmpeg won't die (zombie process)
+ - Icecast mount point stays active
+ - Port not released
+ - State desync (UI thinks stopped, but still running)
+- **Testing & mitigation**
+ - Force-kill if graceful shutdown fails
+ - Explicit Icecast mount unregister
+ - State reconciliation on startup ("What streams are actually running?")
+ - Cleanup orphaned processes on server start
+
+### 2.4 Stream restart (hot reload)
+
+- **What could go wrong?**
+ - Old process dies but new one fails to start
+ - Brief downtime that drops all listeners
+ - Config change invalidates active stream
+- **Testing & mitigation**
+ - Atomic switch: start new before killing old (if source allows)
+ - Graceful handoff with listener notification
+ - Rollback on failure
+
+---
+
+## Layer 3: Audio pipeline
+
+### 3.1 Audio capture
+
+- **What could go wrong?**
+ - Sample rate mismatch (device 48 kHz, expect 44.1 kHz)
+ - Channel mismatch (stereo vs mono)
+ - Device goes silent (mic unplugged, app stops granting permission)
+ - Clipping/distortion (gain too high)
+- **Testing & mitigation**
+ - Auto-detect device capabilities and configure accordingly
+ - Audio level monitoring (alert if silent for > X seconds)
+ - Auto-normalize or gain controls
+ - Fall back to default device if selected fails
+
+### 3.2 Encoding
+
+- **What could go wrong?**
+ - Wrong codec for format (MP3 vs Opus vs AAC)
+ - Bitrate too high for listeners' bandwidth
+ - CPU overload (encoding quality too high)
+- **Testing & mitigation**
+ - Codec compatibility matrix (what works where)
+ - Adaptive bitrate based on listener count
+ - CPU monitoring, quality stepping down if needed
+
+### 3.3 Icecast integration
+
+- **What could go wrong?**
+ - Authentication failure (wrong password in config)
+ - Mount point already exists
+ - Icecast crashes or restarts
+ - Network hiccup between FFmpeg and Icecast
+- **Testing & mitigation**
+ - Connection health monitoring
+ - Auto-reconnect with backoff
+ - Heartbeat/ping to detect Icecast aliveness
+ - Config validation before use
+
+---
+
+## Layer 4: Listener delivery
+
+### 4.1 Stream discovery
+
+- **What could go wrong?**
+ - Listener can't find server (wrong IP, firewall)
+ - Server IP changes (DHCP)
+ - mDNS/Bonjour not working
+- **Testing & mitigation**
+ - Display server IP prominently, include QR code
+ - Link-local addresses (hostname.local)
+ - Simple connectivity test on listener page ("Can I reach the server?")
+
+### 4.2 Playback
+
+- **What could go wrong?**
+ - Browser doesn't support codec
+ - Buffer underruns (stuttering)
+ - High latency (not suitable for translation)
+ - Listener device goes to sleep, loses connection
+- **Testing & mitigation**
+ - Codec fallback cascade (Opus → MP3 → AAC)
+ - Adaptive buffering based on network conditions
+ - Auto-reconnect with UI indication
+ - Latency display (so admin knows if there's an issue)
+
+---
+
+## Layer 5: State & configuration
+
+### 5.1 Persistent state
+
+- **What could go wrong?**
+ - Config file corrupted (bad JSON)
+ - Config file permissions issue
+ - Multiple processes writing to same config
+ - Config schema changes break old configs
+- **Testing & mitigation**
+ - Config validation on load (schema, JSON parse)
+ - Backup/rollback before writes
+ - Atomic file writes (write temp, then rename)
+ - Schema migration path
+
+### 5.2 Runtime state
+
+- **What could go wrong?**
+ - State desync (what's running vs. what we think is running)
+ - Memory leak in long-running process
+ - Event listeners not cleaned up
+- **Testing & mitigation**
+ - State reconciliation function (ask OS "what's actually running")
+ - Regular health checks
+ - Explicit cleanup on all state changes
+
+---
+
+## Layer 6: Error handling & diagnostics
+
+### 6.1 Error detection
+
+- **What could go wrong?**
+ - FFmpeg error patterns not recognized
+ - False positives (normal noise treated as error)
+ - Errors swallowed somewhere in the stack
+- **Testing & mitigation**
+ - Comprehensive error pattern library (errorDiagnostics.js)
+ - Error taxonomy (fatal, recoverable, warning, info)
+ - Error context (stream name, device, timestamp)
+
+### 6.2 Error recovery
+
+- **What could go wrong?**
+ - Retry loop never succeeds (hammering resources)
+ - Recovery makes things worse
+ - User not informed what's happening
+- **Testing & mitigation**
+ - Max retry limits with exponential backoff
+ - Recovery strategies per error type (some need manual intervention)
+ - User-facing messages with actionable next steps
+
+---
+
+## Layer 7: Admin UI
+
+### 7.1 Dashboard
+
+- **What could go wrong?**
+ - UI shows stale state (not synced to backend)
+ - Controls don't work (but don't show error)
+ - Overwhelming amount of information
+- **Testing & mitigation**
+ - Real-time state sync (Socket.io or polling)
+ - Optimistic UI updates with rollback on failure
+ - Progressive disclosure (show essentials, details on demand)
+
+### 7.2 Stream controls
+
+- **What could go wrong?**
+ - Click "Start" but nothing happens
+ - Click "Stop" and it asks "Are you sure?" every time
+ - No indication of what's happening (starting... started... failed)
+- **Testing & mitigation**
+ - Loading states for all async actions
+ - Clear success/error feedback
+ - Keyboard shortcuts for power users
+ - Bulk operations (start all, stop all)
+
+---
+
+## Layer 8: Listener UI
+
+### 8.1 Accessibility
+
+- **What could go wrong?**
+ - Not keyboard navigable
+ - No screen reader support
+ - Poor contrast
+ - Small touch targets on mobile
+- **Testing & mitigation**
+ - WCAG 2.1 AA compliance
+ - Keyboard navigation audit
+ - Screen reader testing
+ - Touch target minimum 44×44 px
+
+### 8.2 Usability
+
+- **What could go wrong?**
+ - Too much information (what do I click?)
+ - No volume control
+ - Can't tell which stream is which
+ - No error state ("Why isn't it playing?")
+- **Testing & mitigation**
+ - Simple primary action: "Play stream"
+ - Stream metadata (name, source, listener count)
+ - Clear error messages with next steps
+ - Mobile-first responsive design
+
+---
+
+## Refactoring path
+
+1. **Layer 1** — Solid environment detection and validation. Everything else depends on this.
+2. **Layer 2 (Lifecycle)** — Clean up how streams are created/started/stopped. Core orchestration.
+3. **Layer 6 (Errors)** — Build the diagnostic system alongside each layer, not after.
+4. **Layer 3 (Audio pipeline)** — Once FFmpeg is reliable, make the audio flow reliable.
+5. **Layers 4, 7, 8 (UI/UX)** — Once the backend is solid, improve the UI thoughtfully.
+
+---
+
+## Scope note: internet streaming
+
+Building internet streaming from scratch is reinventing the wheel. For streaming to the world, use:
+
+- YouTube Live (RTMP)
+- Twitch (RTMP)
+- Restream.io / Castr (multi-platform)
+
+**LANStreamer's strength is local, low-latency, private streaming. Lean into that.**
diff --git a/docs/STARTUP-SEQUENCE.md b/docs/archive/STARTUP-SEQUENCE.md
similarity index 100%
rename from docs/STARTUP-SEQUENCE.md
rename to docs/archive/STARTUP-SEQUENCE.md
diff --git a/docs/TEST-PLAN.md b/docs/archive/TEST-PLAN.md
similarity index 100%
rename from docs/TEST-PLAN.md
rename to docs/archive/TEST-PLAN.md
diff --git a/docs/UI-UX-RECOMMENDATIONS-v2.md b/docs/archive/UI-UX-RECOMMENDATIONS-2026-10.md
similarity index 94%
rename from docs/UI-UX-RECOMMENDATIONS-v2.md
rename to docs/archive/UI-UX-RECOMMENDATIONS-2026-10.md
index 1ba6f51..7df0aba 100644
--- a/docs/UI-UX-RECOMMENDATIONS-v2.md
+++ b/docs/archive/UI-UX-RECOMMENDATIONS-2026-10.md
@@ -1,6 +1,16 @@
-# UI/UX Recommendations for LANStreamer Dashboard v2
+# UI/UX Recommendations for LANStreamer Dashboard
-**Enhanced glassmorphism edition** - inspired by premium frosted glass UI with softer transparency, layered depth, and elegant gradients.
+
+
+**Version 2 — Enhanced glassmorphism edition** (renamed 2026-10-28):
+inspired by premium frosted glass UI with softer transparency, layered
+depth, and elegant gradients. Supersedes Version 1, preserved at
+`docs/archive/UI-UX-RECOMMENDATIONS.md`.
Reference: [Gradient UI/UX Elements](https://www.freepik.com/free-vector/gradient-ui-ux-elements-background_16829080.htm)
@@ -744,3 +754,15 @@ button[aria-label=""] {
- **v2** - Enhanced glassmorphism with premium frosted glass, layered depth, and professional animation curves
- [v1](./UI-UX-RECOMMENDATIONS.md) - Original recommendations with basic glass effects
+
+
+## Version log
+
+- **v2 (2026-10-28)** — glassmorphism edition; renamed from
+ `UI-UX-RECOMMENDATIONS-v2.md` (append-only versioning adopted; v1 archived).
+
+## Version log
+
+- **v2 (2026-10-28)** — glassmorphism edition; renamed from
+ `UI-UX-RECOMMENDATIONS-v2.md` to this append-only file (v1 archived at
+ `docs/archive/UI-UX-RECOMMENDATIONS.md`).
diff --git a/images/.gitkeep b/docs/archive/legacy-images/.gitkeep
similarity index 100%
rename from images/.gitkeep
rename to docs/archive/legacy-images/.gitkeep
diff --git a/images/README.md b/docs/archive/legacy-images/README.md
similarity index 100%
rename from images/README.md
rename to docs/archive/legacy-images/README.md
diff --git a/images/lanstreamer-local-audio-concept-1.jpg b/docs/archive/legacy-images/lanstreamer-local-audio-concept-1.jpg
similarity index 100%
rename from images/lanstreamer-local-audio-concept-1.jpg
rename to docs/archive/legacy-images/lanstreamer-local-audio-concept-1.jpg
diff --git a/images/lanstreamer-local-audio-concept-2.jpg b/docs/archive/legacy-images/lanstreamer-local-audio-concept-2.jpg
similarity index 100%
rename from images/lanstreamer-local-audio-concept-2.jpg
rename to docs/archive/legacy-images/lanstreamer-local-audio-concept-2.jpg
diff --git a/images/lanstreamer-server-terminal.png b/docs/archive/legacy-images/lanstreamer-server-terminal.png
similarity index 100%
rename from images/lanstreamer-server-terminal.png
rename to docs/archive/legacy-images/lanstreamer-server-terminal.png
diff --git a/docs/archive/legacy-images/screenshots/LANStreamer-UI-Review-2026-10-28.pdf b/docs/archive/legacy-images/screenshots/LANStreamer-UI-Review-2026-10-28.pdf
new file mode 100644
index 0000000..0f8dcc8
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/LANStreamer-UI-Review-2026-10-28.pdf differ
diff --git a/images/screenshots/README.md b/docs/archive/legacy-images/screenshots/README.md
similarity index 100%
rename from images/screenshots/README.md
rename to docs/archive/legacy-images/screenshots/README.md
diff --git a/images/screenshots/lanstreamer-dashboard.png b/docs/archive/legacy-images/screenshots/lanstreamer-dashboard.png
similarity index 100%
rename from images/screenshots/lanstreamer-dashboard.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-dashboard.png
diff --git a/images/screenshots/lanstreamer-event-details-form.png b/docs/archive/legacy-images/screenshots/lanstreamer-event-details-form.png
similarity index 100%
rename from images/screenshots/lanstreamer-event-details-form.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-event-details-form.png
diff --git a/images/screenshots/lanstreamer-feedback-contact-details-form.png b/docs/archive/legacy-images/screenshots/lanstreamer-feedback-contact-details-form.png
similarity index 100%
rename from images/screenshots/lanstreamer-feedback-contact-details-form.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-feedback-contact-details-form.png
diff --git a/images/screenshots/lanstreamer-icecast-server-info.png b/docs/archive/legacy-images/screenshots/lanstreamer-icecast-server-info.png
similarity index 100%
rename from images/screenshots/lanstreamer-icecast-server-info.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-icecast-server-info.png
diff --git a/images/screenshots/lanstreamer-login.png b/docs/archive/legacy-images/screenshots/lanstreamer-login.png
similarity index 100%
rename from images/screenshots/lanstreamer-login.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-login.png
diff --git a/images/screenshots/lanstreamer-server-terminal.png b/docs/archive/legacy-images/screenshots/lanstreamer-server-terminal.png
similarity index 100%
rename from images/screenshots/lanstreamer-server-terminal.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-server-terminal.png
diff --git a/images/screenshots/lanstreamer-streams.png b/docs/archive/legacy-images/screenshots/lanstreamer-streams.png
similarity index 100%
rename from images/screenshots/lanstreamer-streams.png
rename to docs/archive/legacy-images/screenshots/lanstreamer-streams.png
diff --git a/images/screenshots/login.png b/docs/archive/legacy-images/screenshots/login.png
similarity index 100%
rename from images/screenshots/login.png
rename to docs/archive/legacy-images/screenshots/login.png
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/01-dashboard-multi-dark.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/01-dashboard-multi-dark.png
new file mode 100644
index 0000000..8d31c65
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/01-dashboard-multi-dark.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/02-dashboard-multi-light.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/02-dashboard-multi-light.png
new file mode 100644
index 0000000..4ad2077
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/02-dashboard-multi-light.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/03-dashboard-add-modal-dark.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/03-dashboard-add-modal-dark.png
new file mode 100644
index 0000000..c4db135
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/03-dashboard-add-modal-dark.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/04-dashboard-add-modal-light.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/04-dashboard-add-modal-light.png
new file mode 100644
index 0000000..db65202
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/04-dashboard-add-modal-light.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/05-dashboard-empty-dark.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/05-dashboard-empty-dark.png
new file mode 100644
index 0000000..e077755
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/05-dashboard-empty-dark.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/06-dashboard-empty-light.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/06-dashboard-empty-light.png
new file mode 100644
index 0000000..94c7b56
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/06-dashboard-empty-light.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/07-listener-desktop-dark.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/07-listener-desktop-dark.png
new file mode 100644
index 0000000..8420764
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/07-listener-desktop-dark.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/08-listener-desktop-light.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/08-listener-desktop-light.png
new file mode 100644
index 0000000..2c17872
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/08-listener-desktop-light.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/09-listener-mobile-dark.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/09-listener-mobile-dark.png
new file mode 100644
index 0000000..65ac73d
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/09-listener-mobile-dark.png differ
diff --git a/docs/archive/legacy-images/screenshots/redesign-2026-10-28/10-listener-mobile-light.png b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/10-listener-mobile-light.png
new file mode 100644
index 0000000..8ba29a1
Binary files /dev/null and b/docs/archive/legacy-images/screenshots/redesign-2026-10-28/10-listener-mobile-light.png differ
diff --git a/docs/benchmark-report-v1.md b/docs/benchmark-report-v1.md
new file mode 100644
index 0000000..9205569
--- /dev/null
+++ b/docs/benchmark-report-v1.md
@@ -0,0 +1,103 @@
+# LANStreamer benchmark report v1 — vs devops practices DB
+
+Date: 2026-10-28 · Procedure: devops `benchmark-practices` skill (Mode B,
+repo filesystem) · DB: 155 records (141 live) post 2026-10-28 promotion.
+Reviewer: ZCode agent, evidence from the committed dev tree (90819e7),
+not any dirty working state.
+
+**Purpose:** first run of the devops↔LANStreamer flywheel — LANStreamer is
+the practices DB's first verified external consumer. Gaps found here feed
+back into the DB as draft records (noted at the end).
+
+Scope: Express API surface (~68 routes across 7 routers), streaming core
+(FFmpeg/Icecast services), uploads, listener static pages, shutdown/startup
+path. Out of scope: Electron shell, PWA assets.
+
+## Verdict: SHIP on LAN · FIX BEFORE ANY WIDER EXPOSURE
+
+0 blockers (LAN threat model) · 3 should-fix · 1 nice · 4 compliant ·
+3 undetermined · 2 DB gaps surfaced.
+
+## Should-fix (fix before exposing beyond the LAN)
+
+1. **Upload extension/content-type allowlist missing** (uploads land in a
+ static-served dir) — `src/routes/contact.js:18` writes to
+ `public/uploads/events`, served by `express.static` (`src/app.js:25`);
+ `filename()` keeps the user-controlled extension (`contact.js:27-31`,
+ `settings.js:25-32`). `event_.html` / `.svg` = stored scriptable
+ content any LAN device can be lured to. `path.basename` blocks traversal
+ (good) but nothing restricts type. Fix: multer `fileFilter` allowlist
+ (jpg/png/webp/mp3 per route) + serve uploads with
+ `Content-Disposition: attachment` or a separate non-executable handler.
+ *(No devops record exists for upload validation — gap #1 below.)*
+2. **Rate limiting configured but not wired** — `src/config/index.js:95-96`
+ defines RATE_LIMIT_* (100/15min defaults) but no limiter middleware is
+ applied anywhere (no express-rate-limit dep, no usage). Remaining
+ auth/login/setup endpoints are unlimited. Violates **SEC-AUTH-001**
+ (rate-limit every auth endpoint) — mitigated by LAN-only exposure and
+ the localhost admin lock, but the config suggests an intent that was
+ never landed. Fix: wire `express-rate-limit` on `/api/auth`, `/api/setup`.
+3. **Config persistence is not atomic** — `config/streams.json` and
+ `data/streams.json` written in place by StreamingService (no tmp+rename
+ found). A crash mid-write corrupts stream definitions. Violates the
+ atomic-write discipline referenced by **REL-ASY-009** / **DATA-001**
+ (wrap multi-write state changes atomically; for file stores that means
+ write-temp-then-rename). Fix: `fs.writeFile(tmp)` + `fs.rename`.
+
+## Nice
+
+4. **PERF-006 (health checks must mean work, not liveness)** —
+ `src/app.js:30` `/api/health` exists and is used by tests; verify it
+ reflects Icecast/FFmpeg ability (current shape undetermined from route
+ stub — if it only returns 200, add a degraded state when the source
+ engine is down).
+
+## Compliant (evidence)
+
+- **Graceful shutdown wired** — SIGINT/SIGTERM handlers stop streams then
+ exit (`src/server.js:72,127-135`), services stop ordered with timeout
+ (`src/app.js` shutdown). *(Pattern has no DB record — gap #2.)*
+- **Admin surface locked to localhost** — `requireLocalhostAdmin`
+ middleware (`src/app.js:27`), integration-tested
+ (`tests/integration/lock-admin-localhost.test.js`). Authorization
+ boundary consistent with **SEC-AUTHZ-001/002** intent.
+- **REL-ASY-009 (test by making the world miserable)** — errorScenarios,
+ stream-start-error, ffmpeg-spawn, reorder tests exist
+ (`tests/integration/`, `tests/scenarios/`) — genuinely strong for this
+ category.
+- **Upload size limits set** — 2MB images / 200MB music
+ (`contact.js:36-40`, `settings.js:33-37`).
+
+## Undetermined (check next round)
+
+- **REL-ASY-001 (non-essential out of request cycle)** — is FFmpeg spawn
+ async relative to the HTTP response? Tests suggest yes; not verified
+ line-level.
+- **REL-ASY-006 (timeouts/backoff on downstream)** — Icecast/FFmpeg
+ dependency timeouts not audited.
+- JWT middleware remains (`src/middleware/auth.js`) after the auth-removal
+ commit — confirm no dead privileged path still trusts it.
+
+## DB gaps surfaced (feed back into devops)
+
+1. **Upload validation record** — allowlist type+extension, randomize
+ stored name, never serve user uploads as executable content. (Source
+ candidate: this benchmark + OWASP unrestr. upload guidance.)
+2. **Graceful shutdown record** — SIGTERM → stop accepting → drain/stop
+ children → bounded timeout → exit; health endpoint flips first.
+ (Source candidates: LANStreamer server.js, 12-factor disposability.)
+
+Both are queued as draft candidates for the next ingestion round, keeping
+SCHEMA rule 1 in mind: this report is the source, so future LANStreamer
+compliance is self-consistent, not independent.
+
+## Scorecard
+
+| severity | count |
+|---|---|
+| blocker | 0 |
+| should (fix) | 3 |
+| nice | 1 |
+| compliant evidenced | 4 |
+| undetermined | 3 |
+| DB gaps surfaced | 2 |
diff --git a/docs/guides/README.md b/docs/guides/README.md
index f996ca6..02a72d2 100644
--- a/docs/guides/README.md
+++ b/docs/guides/README.md
@@ -2,15 +2,16 @@
> **Simple, step-by-step guides for non-technical users**
-## 📦 Required Software Installation
+> **Packaged app (installer):** you can skip this page — FFmpeg and Icecast are bundled with the app.
+> **Running from source (repo/ZIP or server-only):** install both programs below first.
-**Before using LANStreamer, you need to install these two programs:**
+## 📦 Required Software Installation (source installs)
### Essential Components
- **[FFmpeg Installation](./ffmpeg-installation.md)** - Audio processor (5 minutes) ⭐ **Start here**
- **[Icecast Installation](./icecast-installation.md)** - Streaming server (5 minutes)
-> **💡 Why do I need these?** LANStreamer is a web application that coordinates these two powerful tools to create your streaming server. Think of LANStreamer as the "control panel" and FFmpeg/Icecast as the "engines" that do the actual work.
+> **💡 Why do I need these?** LANStreamer coordinates these two powerful tools to create your streaming server. Think of LANStreamer as the "control panel" and FFmpeg/Icecast as the "engines" that do the actual work.
### 🎧 Understanding LANStreamer
- **[Audio Pipeline Concepts](./audio-pipeline-simple.md)** - How audio flows from source to listeners
diff --git a/docs/pressure-checklist.md b/docs/pressure-checklist.md
new file mode 100644
index 0000000..cd19531
--- /dev/null
+++ b/docs/pressure-checklist.md
@@ -0,0 +1,41 @@
+# Pressure Checklist (pre-review gate for streaming features)
+
+Adopted from the devops practices database (playbook: pressure-checklist,
+originally from system-design-book@ Ch 0.3), 2026-10-28.
+
+**Gate rule:** every PR that adds or changes streaming behavior (stream
+lifecycle, proxying, device capture, listener fanout, start-all, queueing)
+must answer these 7 conditions for the changed code path in the PR
+description — not in the reviewer's head. A design that only survives on
+paper (untested fallbacks, guessed timeout numbers) counts as failing.
+
+1. **Load is uneven** — month end, holiday peaks, campaign spikes.
+ Design target: peak-to-average ratio (often 3x+).
+2. **A dependency is SLOW, not down** — 8 seconds. Worse than down:
+ callers keep waiting, resources fill, failure travels upward.
+ Ask: what is my capacity at concurrency ÷ 8s?
+ (LANStreamer shape: Icecast slow-but-alive, FFmpeg device stalls,
+ SMB/network drive source reads.)
+3. **Data is 10x expected** — the table you never thought would grow.
+ Ask: do indexes, partitions, and queries survive 10x?
+ (LANStreamer shape: config/streams.json entries, uploads dir, logs.)
+4. **A machine disappears mid-write / mid-transaction** — is the
+ invariant preserved? (atomicity, durable execution)
+ (LANStreamer shape: FFmpeg killed mid-spawn, stream state file
+ rewritten during crash, lock-file races.)
+5. **The network is poor** — high latency, packet loss, flaky mobile.
+ Round-trip count becomes the dominant cost.
+ (LANStreamer shape: listener page over WAN/LAN, QR-share links.)
+6. **The same request arrives twice** — user tapped Send again.
+ Ask: idempotency key? dedupe committed with the side effect?
+ (LANStreamer shape: start/stop double-clicks, start-all re-entry,
+ reorder + delete racing.)
+7. **Traffic is hostile** — someone is enumerating endpoints,
+ spamming auth routes, replaying webhooks.
+ (LANStreamer shape: LAN exposure, uploads endpoint abuse.)
+
+## Why a fixed set
+
+So quality doesn't depend on who happens to be in the room. The same
+seven questions every time, and the answers live in the PR record, not in
+chat scrollback.
diff --git a/electron/icon.ico b/electron/icon.ico
new file mode 100644
index 0000000..65d1e73
Binary files /dev/null and b/electron/icon.ico differ
diff --git a/electron/main.js b/electron/main.js
new file mode 100644
index 0000000..cc935f6
--- /dev/null
+++ b/electron/main.js
@@ -0,0 +1,493 @@
+import { app, BrowserWindow, Tray, Menu, nativeImage, dialog, shell, powerSaveBlocker, powerMonitor, ipcMain } from 'electron';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { spawn, execSync } from 'child_process';
+import { createRequire } from 'module';
+
+const require = createRequire(import.meta.url);
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+
+const SMOKE = process.argv.includes('--smoke') || process.env.ELECTRON_SMOKE === '1';
+const BASE_PORT = parseInt(process.env.PORT || '3001', 10);
+
+// Bundled binaries + writable data dir for PACKAGED installs — must be set
+// before the server code below imports, so services resolve the vendored
+// FFmpeg/Icecast (resources/vendor) and keep config/logs in userData.
+if (app.isPackaged && !process.env.LANSTREAMER_VENDOR_DIR) {
+ process.env.LANSTREAMER_VENDOR_DIR = path.join(process.resourcesPath, 'vendor');
+ process.env.LANSTREAMER_DATA_DIR = app.getPath('userData');
+}
+
+let mainWindow = null;
+let tray = null;
+let serverHandle = null;
+let isQuitting = false;
+
+// ---------------------------------------------------------------------------
+// Server lifecycle (Express in-process; listeners on the LAN keep working)
+// ---------------------------------------------------------------------------
+
+// Credential policy (owner decision 2026-10-30): DOCUMENTED defaults + prompt
+// to change (dashboard banner + Admin account card) + a documented recovery
+// path (delete the security file → defaults return). Random per-install
+// minting was tried and reverted as overkill: the localhost lock already
+// keeps the LAN out of the admin panel, and the operator must stay in full
+// control. The LAN-facing hardening lives on bundled Icecast instead
+// (loopback bind + per-install random passwords in its generated config).
+
+const { startServer } = await import('../src/app.js');
+
+function listenWithFallback(basePort, attempts = 5) {
+ return new Promise((resolve, reject) => {
+ const tryPort = (port, left) => {
+ const handle = startServer({ port });
+ handle.server.once('error', (err) => {
+ try { handle.server.close(); } catch { /* not listening anyway */ }
+ if (err.code === 'EADDRINUSE' && left > 0) {
+ tryPort(port + 1, left - 1);
+ } else {
+ reject(err);
+ }
+ });
+ handle.server.once('listening', () => resolve(handle));
+ };
+ tryPort(basePort, attempts);
+ });
+}
+
+/**
+ * Kill a process and its whole tree. Windows child_process does NOT kill
+ * descendants on parent exit, so orphaned FFmpeg/Icecast would keep the audio
+ * device and ports locked after the app closes.
+ */
+function treeKill(pid) {
+ if (!pid) return;
+ if (process.platform === 'win32') {
+ spawn('taskkill', ['/pid', String(pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
+ } else {
+ try { process.kill(pid, 'SIGTERM'); } catch { /* already gone */ }
+ }
+}
+
+/**
+ * Startup sweep after a crash / End-Task (Windows never reaps children of a
+ * dead parent): stale ffmpeg/icecast keep the audio device and ports locked.
+ * Matched by EXECUTABLE PATH under a LANStreamer vendor dir — never by
+ * process name, so the user's own FFmpeg/VoiceMeeter processes are untouchable.
+ */
+function sweepOrphanChildren() {
+ if (process.platform !== 'win32') return 0;
+ try {
+ // No nested double quotes: cmd.exe strips the outer pair, and an inner
+ // pair would terminate the -Command string early (the smoke run hit
+ // "positional parameter cannot be found that accepts argument 'or'").
+ // Single quotes only inside; filter via Where-Object instead of -Filter.
+ const out = execSync(
+ `powershell -NoProfile -Command "Get-CimInstance Win32_Process | ` +
+ `Where-Object { $_.Name -eq 'ffmpeg.exe' -or $_.Name -eq 'icecast.exe' } | ` +
+ `Where-Object { $_.ExecutablePath -like '*LANStreamer*vendor*' } | ` +
+ `ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue; $_.ProcessId }"`,
+ { encoding: 'utf8', windowsHide: true, timeout: 15000 }
+ ).trim();
+ const pids = out.split(/\s+/).filter(Boolean);
+ if (pids.length) console.log(`[electron] startup sweep killed ${pids.length} orphaned vendor process(es): ${pids.join(', ')}`);
+ return pids.length;
+ } catch {
+ return 0; // sweep is best-effort — never block startup on it
+ }
+}
+
+async function shutdownBackend() {
+ const streamingService = (await import('../src/services/StreamingService.js')).default;
+ const icecastService = (await import('../src/services/IcecastService.js')).default;
+
+ try {
+ await streamingService.stopAllStreams();
+ } catch (err) {
+ console.error('[electron] stopAllStreams failed:', err.message);
+ }
+
+ // Belt-and-braces: tree-kill anything the services left behind
+ // (activeStreams entries carry ffmpegProcess — entry.process was a typo
+ // that made this safety net a no-op)
+ for (const entry of Object.values(streamingService.activeStreams || {})) {
+ const proc = entry?.ffmpegProcess;
+ if (proc?.pid && proc.exitCode === null) treeKill(proc.pid);
+ }
+ if (icecastService.process?.pid && !icecastService.process.killed) {
+ try { await icecastService.stop(false); } catch { /* ignore */ }
+ // stop() NULLS the process reference on success — re-read defensively
+ // (a bare .killed here crashed the smoke shutdown: "reading 'killed' of null")
+ if (icecastService.process?.pid && !icecastService.process.killed) {
+ treeKill(icecastService.process.pid);
+ }
+ }
+
+ if (serverHandle) {
+ // Streams + icecast were already stopped above (ordered, with belt-and-
+ // braces tree-kills) — skip the duplicate pass inside shutdown.
+ await serverHandle.shutdown({ timeoutMs: 4000, stopStreams: false });
+ serverHandle = null;
+ }
+
+ const telemetry = (await import('../src/services/TelemetryService.js')).default;
+ await telemetry.shutdown();
+}
+
+// ---------------------------------------------------------------------------
+// Window + tray
+// ---------------------------------------------------------------------------
+
+function getIcon() {
+ const img = nativeImage.createFromPath(path.join(__dirname, '..', 'public', 'assets', 'favicon.png'));
+ if (img.isEmpty()) console.warn('[electron] icon image is empty/missing — tray may be invisible');
+ return img;
+}
+
+function createWindow() {
+ mainWindow = new BrowserWindow({
+ width: 1280,
+ height: 800,
+ minWidth: 1024,
+ minHeight: 600,
+ icon: getIcon(),
+ backgroundColor: '#0f0c29',
+ autoHideMenuBar: true,
+ show: false,
+ webPreferences: {
+ contextIsolation: true,
+ nodeIntegration: false,
+ preload: path.join(__dirname, 'preload.js'), // window.LSApp — minimize/shutdown bridge
+ },
+ });
+
+ mainWindow.once('ready-to-show', () => mainWindow.show());
+
+ // A dead renderer with hide-on-close + tray-only quit = white window with no
+ // recovery. Reload instead.
+ mainWindow.webContents.on('render-process-gone', (_e, details) => {
+ if (details.reason !== 'clean-exit') {
+ console.error('[electron] renderer gone:', details.reason, '— reloading');
+ mainWindow.reload();
+ }
+ });
+
+ // Links like "Listen to Streams" (and any external URL) open in the user's
+ // system browser, not a child Electron window. The listener page is meant
+ // for phones/other machines anyway.
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
+ if (url.startsWith('http://') || url.startsWith('https://')) {
+ shell.openExternal(url);
+ }
+ return { action: 'deny' };
+ });
+ mainWindow.webContents.on('will-navigate', (e, url) => {
+ // Keep in-app navigation confined to our own dashboard
+ if (!url.startsWith(`http://localhost:`)) {
+ e.preventDefault();
+ shell.openExternal(url);
+ }
+ });
+
+ mainWindow.loadURL(`http://localhost:${serverHandle.port}/dashboard`);
+
+ // Alt-accessible menu with a real Exit — insurance for the worst case of an
+ // invisible tray icon + hide-on-close, which would otherwise be unexitable.
+ Menu.setApplicationMenu(Menu.buildFromTemplate([
+ { label: 'File', submenu: [{ label: 'Exit', click: () => { isQuitting = true; shutdownBackend().finally(() => app.quit()); } }] },
+ { role: 'editMenu' },
+ { role: 'viewMenu' },
+ ]));
+
+ // Tray mode: closing the window must NOT stop streams for LAN listeners.
+ // Real exit only happens through the tray's "Stop All & Quit".
+ mainWindow.on('close', (e) => {
+ if (!isQuitting) {
+ e.preventDefault();
+ mainWindow.hide();
+ }
+ });
+
+ mainWindow.on('closed', () => { mainWindow = null; });
+}
+
+async function createTray() {
+ const telemetry = (await import('../src/services/TelemetryService.js')).default;
+ const telemetryItem = {
+ label: `Telemetry: ${telemetry.getConsentState().enabled ? 'On' : 'Off'}`,
+ click: async () => {
+ const state = telemetry.getConsentState();
+ telemetry.setConsented(!state.enabled);
+ createTray().catch(err => console.error('[electron] tray refresh failed:', err.message));
+ },
+ };
+
+ // Tray is a native handle — destroy the old one before reassigning, or every
+ // telemetry toggle leaks it (and stacks ghost icons on some Windows builds).
+ if (tray) { try { tray.destroy(); } catch { /* already gone */ } tray = null; }
+ tray = new Tray(getIcon());
+ tray.setToolTip('LANStreamer');
+
+ const menu = Menu.buildFromTemplate([
+ { label: 'Show Dashboard', click: () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } } },
+ { type: 'separator' },
+ { label: 'Telemetry', submenu: [telemetryItem] },
+ { type: 'separator' },
+ {
+ label: 'Stop All & Quit',
+ click: async () => {
+ isQuitting = true;
+ await shutdownBackend();
+ app.quit();
+ },
+ },
+ ]);
+
+ tray.setContextMenu(menu);
+ tray.on('double-click', () => { if (mainWindow) mainWindow.show(); });
+}
+
+// ---------------------------------------------------------------------------
+// App control from the dashboard header (window.LSApp via preload.js)
+// ---------------------------------------------------------------------------
+
+ipcMain.on('ls:minimize', () => {
+ if (!mainWindow || isQuitting) return;
+ mainWindow.hide();
+ // Windows balloon: self-expiring toast from the tray — tells the operator
+ // the app is alive in the tray and listeners keep their audio.
+ try {
+ if (tray && typeof tray.displayBalloon === 'function') {
+ tray.displayBalloon({
+ iconType: 'info',
+ title: 'LANStreamer is still running',
+ content: 'It lives in the tray now — streams keep playing for your listeners. Double-click the tray icon to reopen the dashboard.'
+ });
+ }
+ } catch { /* balloons are best-effort (older Windows may suppress them) */ }
+});
+
+ipcMain.on('ls:shutdown', async () => {
+ if (!mainWindow || isQuitting) return;
+ // cheap read: any live stream means listeners lose audio on shutdown
+ // (dynamic import — module already loaded in-process, resolves instantly)
+ let running = false;
+ try {
+ const streamingService = (await import('../src/services/StreamingService.js')).default;
+ running = Object.values(streamingService.activeStreams || {}).some(s => s.status === 'running');
+ } catch { /* default to the calmer wording */ }
+
+ const { response } = await dialog.showMessageBox(mainWindow, {
+ type: 'warning',
+ title: 'Shut down LANStreamer?',
+ message: 'Shut down LANStreamer?',
+ detail: running
+ ? 'Streams are LIVE — shutting down stops them all and every listener loses audio. The dashboard, streams and Icecast all close.'
+ : 'The dashboard, streams and Icecast all close. (No streams are live right now.)',
+ buttons: ['Cancel', 'Shut down'],
+ defaultId: 0,
+ cancelId: 0,
+ noLink: true,
+ });
+ if (response !== 1) return;
+
+ isQuitting = true;
+ await shutdownBackend().catch(err => console.error('[electron] shutdown error:', err.message));
+ app.quit();
+});
+
+/**
+ * First-run telemetry NOTICE (owner decision 2026-11-01: opt-out — telemetry
+ * is ON unless explicitly turned off). Shows once, states plainly what is
+ * collected, and offers a one-click "Turn off". Change anytime: dashboard
+ * Admin account card switch, or tray icon → Telemetry → On/Off.
+ *
+ * FIX (2026-11-01, Jerry's install report): this check RACES the telemetry
+ * service's async init — getKey() read before _loadState finishes returns
+ * null and the prompt silently never shows (and never retries). init() is
+ * idempotent, so await it here first: the prompt is guaranteed to see the
+ * real key + consent state.
+ */
+async function maybeAskTelemetryConsent() {
+ const telemetry = (await import('../src/services/TelemetryService.js')).default;
+ await telemetry.init(); // idempotent — ensures key/consent state is loaded
+ const state = telemetry.getConsentState();
+ if (state.consented !== null || !telemetry.getKey()) return; // decided, or nothing to enable
+
+ const { response } = await dialog.showMessageBox(mainWindow, {
+ type: 'info',
+ title: 'LANStreamer — anonymous usage statistics: ON',
+ message: 'Anonymous usage statistics are ON for this install.',
+ detail: 'LANStreamer is free and open source — no one profits from it. '
+ + 'To keep improving it, this install sends anonymous events '
+ + '(app start/stop, stream started/stopped/failed, app version, OS) to the '
+ + 'maintainer\u2019s PostHog.\n\n'
+ + 'No audio, no stream names, no personal data — and listeners\u2019 phones never send anything.\n\n'
+ + 'Turn it off anytime: the dashboard Admin account card switch, or tray icon \u2192 Telemetry \u2192 On/Off.',
+ buttons: ['OK, keep it on', 'Turn it off'],
+ defaultId: 0,
+ cancelId: 0,
+ noLink: true,
+ });
+
+ telemetry.setConsented(response !== 1); // 0 = keep on (persisted), 1 = off
+ createTray(); // refresh the tray label
+}
+
+// ---------------------------------------------------------------------------
+// App lifecycle
+// ---------------------------------------------------------------------------
+
+const gotLock = app.requestSingleInstanceLock();
+if (!gotLock) {
+ app.quit();
+} else {
+ app.on('second-instance', () => {
+ if (mainWindow) {
+ mainWindow.show();
+ mainWindow.focus();
+ }
+ });
+
+ // Tray mode: closing all windows never quits the app
+ app.on('window-all-closed', (e) => { /* keep running for LAN listeners */ });
+
+ app.whenReady().then(async () => {
+ // Packaged data dir must exist before server code writes config/logs into it
+ if (app.isPackaged) {
+ try { require('node:fs').mkdirSync(process.env.LANSTREAMER_DATA_DIR, { recursive: true }); } catch { /* best effort */ }
+ }
+
+ // Free audio devices/ports held by children of a previous crashed session
+ sweepOrphanChildren();
+
+ try {
+ serverHandle = await listenWithFallback(BASE_PORT);
+ } catch (err) {
+ dialog.showErrorBox('LANStreamer', `Could not start the local server: ${err.message}`);
+ app.quit();
+ return;
+ }
+
+ // Port fallback = a leftover LANStreamer/server almost certainly owns the
+ // base port. Two instances sharing one config cause stream conflicts —
+ // surface it instead of silently running on 3002+.
+ if (serverHandle.port !== BASE_PORT && !SMOKE) {
+ dialog.showMessageBox(null, {
+ type: 'warning',
+ title: 'LANStreamer',
+ message: `LANStreamer started on port ${serverHandle.port} (port ${BASE_PORT} was already in use).`,
+ detail: 'Another LANStreamer server — probably a leftover instance — is likely still running. Two servers sharing one configuration cause stream conflicts and "device busy" errors.\n\nStop the other instance (close its terminal window, or quit the other app from its tray), then relaunch. See the in-app guide (/docs) → "port already in use".',
+ buttons: ['Continue anyway', 'Quit now'],
+ defaultId: 1,
+ noLink: true,
+ }).then(({ response }) => {
+ if (response === 1) { isQuitting = true; shutdownBackend().finally(() => app.quit()); }
+ }).catch(() => { /* dialog never blocks boot */ });
+ }
+
+ const os = require('node:os');
+ const lanIp = Object.values(os.networkInterfaces())
+ .flat()
+ .find(i => i && i.family === 'IPv4' && !i.internal && /^(192\.168|10\.|172\.(1[6-9]|2\d|3[01]))/.test(i.address));
+ console.log(`[electron] server ready on port ${serverHandle.port}`);
+ console.log(`[electron] listener page: http://${lanIp ? lanIp.address : 'localhost'}:${serverHandle.port}/streams`);
+
+ createWindow();
+ createTray().catch(err => console.error('[electron] tray creation failed:', err.message));
+ maybeAskTelemetryConsent().catch(err => console.error('[electron] telemetry prompt failed:', err.message));
+
+ startPowerManagement();
+
+ if (SMOKE) {
+ mainWindow.webContents.once('did-finish-load', () => {
+ console.log('SMOKE_OK');
+ setTimeout(() => {
+ isQuitting = true;
+ shutdownBackend().catch(err => console.error('[electron] smoke shutdown error:', err.message)).finally(() => app.exit(0));
+ }, 1500);
+ });
+ }
+ }).catch(err => {
+ dialog.showErrorBox('LANStreamer', `Startup failed: ${err && err.message}`);
+ app.quit();
+ });
+
+ app.on('before-quit', (e) => {
+ if (!isQuitting) {
+ e.preventDefault();
+ isQuitting = true;
+ shutdownBackend().catch(err => console.error('[electron] shutdown error:', err.message)).finally(() => app.quit());
+ }
+ });
+
+ // One policy for the unexpected in a packaged app (no console to see it in):
+ // surface it, then take the ordered shutdown path instead of orphaning children.
+ const crashPolicy = (label) => (err) => {
+ console.error(`[electron] ${label}:`, err);
+ try {
+ dialog.showErrorBox('LANStreamer', `An unexpected error occurred:\n\n${err && (err.stack || err.message)}\n\nThe app will now shut down.`);
+ } catch { /* dialogs can fail headless */ }
+ isQuitting = true;
+ shutdownBackend().catch(() => {}).finally(() => app.exit(1));
+ };
+ process.on('uncaughtException', crashPolicy('uncaught exception'));
+ // The smoke run surfaced this class separately: async failures reject, they
+ // don't throw — without this handler they surface only as console noise.
+ process.on('unhandledRejection', crashPolicy('unhandled rejection'));
+}
+
+/**
+ * Power edge cases: Windows suspending mid-broadcast kills the stream silently
+ * (the event-killer), and after resume, FFmpeg has usually died on the device.
+ * - While ANY stream is live: block system suspension (audio keeps flowing
+ * with the display off — 'prevent-app-suspension', not screen-wake).
+ * - On resume: bring back streams that were live before suspend.
+ */
+async function startPowerManagement() {
+ // Module is already loaded (server boots it) — this import resolves instantly
+ const streamingService = (await import('../src/services/StreamingService.js')).default;
+ let blockerId = null;
+ let liveBeforeSuspend = [];
+
+ setInterval(() => {
+ try {
+ const running = (streamingService.getStats().streams || []).filter(s => s.status === 'running').length;
+ if (running > 0 && blockerId === null) {
+ blockerId = powerSaveBlocker.start('prevent-app-suspension');
+ console.log(`[electron] powerSaveBlocker on (${running} live stream${running > 1 ? 's' : ''})`);
+ } else if (running === 0 && blockerId !== null) {
+ powerSaveBlocker.stop(blockerId);
+ blockerId = null;
+ console.log('[electron] powerSaveBlocker off (no live streams)');
+ }
+ } catch { /* stats unavailable during teardown */ }
+ }, 5000).unref?.();
+
+ powerMonitor.on('suspend', () => {
+ try {
+ liveBeforeSuspend = (streamingService.getStats().streams || []).filter(s => s.status === 'running').map(s => s.id);
+ if (liveBeforeSuspend.length) console.log(`[electron] suspend with ${liveBeforeSuspend.length} live stream(s) — will restore on resume`);
+ } catch { liveBeforeSuspend = []; }
+ });
+
+ powerMonitor.on('resume', async () => {
+ if (!liveBeforeSuspend.length) return;
+ const ids = liveBeforeSuspend;
+ liveBeforeSuspend = [];
+ console.log('[electron] resume — restoring streams in 5s:', ids.join(', '));
+ await new Promise(r => setTimeout(r, 5000)); // let devices/network settle
+ for (const id of ids) {
+ try {
+ const current = (streamingService.getStats().streams || []).find(s => s.id === id);
+ if (current && current.status !== 'running') {
+ await streamingService.restartStream(id);
+ console.log(`[electron] restored stream ${id} after resume`);
+ }
+ } catch (err) {
+ console.error(`[electron] could not restore stream ${id} after resume:`, err.message);
+ }
+ }
+ });
+}
diff --git a/electron/preload.js b/electron/preload.js
new file mode 100644
index 0000000..5b8eb42
--- /dev/null
+++ b/electron/preload.js
@@ -0,0 +1,16 @@
+/**
+ * Preload bridge — the ONLY surface the dashboard renderer gets for app
+ * control (contextIsolation stays on, nodeIntegration stays off).
+ *
+ * window.LSApp.minimize() → hide to tray (streams keep running) + balloon
+ * window.LSApp.shutdown() → confirmation dialog → ordered app shutdown
+ *
+ * Pages served to plain browsers (no preload) see no LSApp and hide the
+ * app-control buttons accordingly.
+ */
+const { contextBridge, ipcRenderer } = require('electron');
+
+contextBridge.exposeInMainWorld('LSApp', {
+ minimize: () => ipcRenderer.send('ls:minimize'),
+ shutdown: () => ipcRenderer.send('ls:shutdown')
+});
diff --git a/env.example b/env.example
new file mode 100644
index 0000000..297e83f
--- /dev/null
+++ b/env.example
@@ -0,0 +1,22 @@
+# LANStreamer environment template.
+# Copy to .env and fill in real values. NEVER commit your real .env.
+
+# --- Admin credentials (CHANGE THESE before any real event) ---
+ADMIN_USERNAME=admin
+ADMIN_PASSWORD=change-me-now
+JWT_SECRET=generate-a-long-random-string
+SESSION_SECRET=generate-another-long-random-string
+
+# --- Server ---
+PORT=3001
+HOST=0.0.0.0
+
+# --- External tools (optional; auto-detected when omitted) ---
+# ICECAST_EXE_PATH=C:\path\to\icecast.exe
+# ICECAST_CONFIG_PATH=C:\path\to\icecast.xml
+
+# --- Telemetry (optional; off unless users consent) ---
+# Get the key from your PostHog project settings. Nothing is sent without
+# per-install consent (first-run prompt; toggle in the tray menu).
+# POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxx
+# POSTHOG_HOST=https://eu.i.posthog.com
diff --git a/gui-test-screenshots/fix-dashboard.jpg b/gui-test-screenshots/fix-dashboard.jpg
new file mode 100644
index 0000000..c79f7b6
Binary files /dev/null and b/gui-test-screenshots/fix-dashboard.jpg differ
diff --git a/gui-test-screenshots/fix-listener-playing.jpg b/gui-test-screenshots/fix-listener-playing.jpg
new file mode 100644
index 0000000..17d5a5d
Binary files /dev/null and b/gui-test-screenshots/fix-listener-playing.jpg differ
diff --git a/gui-test-screenshots/p1-dashboard-light.jpg b/gui-test-screenshots/p1-dashboard-light.jpg
new file mode 100644
index 0000000..6fc936c
Binary files /dev/null and b/gui-test-screenshots/p1-dashboard-light.jpg differ
diff --git a/gui-test-screenshots/p2-dashboard.jpg b/gui-test-screenshots/p2-dashboard.jpg
new file mode 100644
index 0000000..7dbf0b1
Binary files /dev/null and b/gui-test-screenshots/p2-dashboard.jpg differ
diff --git a/gui-test-screenshots/p3-drawer.jpg b/gui-test-screenshots/p3-drawer.jpg
new file mode 100644
index 0000000..10ccc66
Binary files /dev/null and b/gui-test-screenshots/p3-drawer.jpg differ
diff --git a/gui-test-screenshots/p4-listener-dark.jpg b/gui-test-screenshots/p4-listener-dark.jpg
new file mode 100644
index 0000000..557735e
Binary files /dev/null and b/gui-test-screenshots/p4-listener-dark.jpg differ
diff --git a/gui-test-screenshots/p4-listener-light.jpg b/gui-test-screenshots/p4-listener-light.jpg
new file mode 100644
index 0000000..00086b5
Binary files /dev/null and b/gui-test-screenshots/p4-listener-light.jpg differ
diff --git a/gui-test-screenshots/p4-listener-mobile.jpg b/gui-test-screenshots/p4-listener-mobile.jpg
new file mode 100644
index 0000000..824ad78
Binary files /dev/null and b/gui-test-screenshots/p4-listener-mobile.jpg differ
diff --git a/gui-test-screenshots/probe-drawer-light.jpg b/gui-test-screenshots/probe-drawer-light.jpg
new file mode 100644
index 0000000..7daf79d
Binary files /dev/null and b/gui-test-screenshots/probe-drawer-light.jpg differ
diff --git a/gui-test-screenshots/r3-duplicate-error.jpg b/gui-test-screenshots/r3-duplicate-error.jpg
new file mode 100644
index 0000000..9018bd8
Binary files /dev/null and b/gui-test-screenshots/r3-duplicate-error.jpg differ
diff --git a/gui-test-screenshots/t2-showcase-light.jpg b/gui-test-screenshots/t2-showcase-light.jpg
new file mode 100644
index 0000000..e056dfe
Binary files /dev/null and b/gui-test-screenshots/t2-showcase-light.jpg differ
diff --git a/gui-test-screenshots/t3-after-burst.jpg b/gui-test-screenshots/t3-after-burst.jpg
new file mode 100644
index 0000000..e250b40
Binary files /dev/null and b/gui-test-screenshots/t3-after-burst.jpg differ
diff --git a/gui-test-screenshots/t3-before.jpg b/gui-test-screenshots/t3-before.jpg
new file mode 100644
index 0000000..4995b33
Binary files /dev/null and b/gui-test-screenshots/t3-before.jpg differ
diff --git a/gui-test-screenshots/t4-connecting.jpg b/gui-test-screenshots/t4-connecting.jpg
new file mode 100644
index 0000000..0a8d868
Binary files /dev/null and b/gui-test-screenshots/t4-connecting.jpg differ
diff --git a/gui-test-screenshots/t4-replaced.jpg b/gui-test-screenshots/t4-replaced.jpg
new file mode 100644
index 0000000..694e158
Binary files /dev/null and b/gui-test-screenshots/t4-replaced.jpg differ
diff --git a/gui-test-screenshots/t5-bell-panel-fixed.jpg b/gui-test-screenshots/t5-bell-panel-fixed.jpg
new file mode 100644
index 0000000..04bdfa7
Binary files /dev/null and b/gui-test-screenshots/t5-bell-panel-fixed.jpg differ
diff --git a/gui-test-screenshots/t6-modal-dark.jpg b/gui-test-screenshots/t6-modal-dark.jpg
new file mode 100644
index 0000000..471aa8a
Binary files /dev/null and b/gui-test-screenshots/t6-modal-dark.jpg differ
diff --git a/gui-test-screenshots/t6-modal-light.jpg b/gui-test-screenshots/t6-modal-light.jpg
new file mode 100644
index 0000000..0b6f1aa
Binary files /dev/null and b/gui-test-screenshots/t6-modal-light.jpg differ
diff --git a/package-lock.json b/package-lock.json
index 25f5263..ec541c9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "lanstreamer-server",
- "version": "1.2.3",
+ "version": "1.2.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lanstreamer-server",
- "version": "1.2.3",
+ "version": "1.2.4",
"license": "ISC",
"dependencies": {
"dotenv": "^17.2.1",
@@ -15,17 +15,36 @@
"jsonwebtoken": "^9.0.2",
"multer": "^2.0.2",
"node-fetch": "^3.3.2",
+ "posthog-node": "^5.56.4",
+ "qrcode": "^1.5.4",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
"xml2js": "^0.6.2"
},
"devDependencies": {
+ "@tailwindcss/container-queries": "^0.1.1",
+ "@tailwindcss/forms": "^0.5.11",
"@types/jest": "^30.0.0",
- "browser-sync": "^3.0.4",
+ "electron": "^45.0.0",
+ "electron-builder": "^26.18.0",
"jest": "^30.2.0",
"nodemon": "^2.0.0",
"puppeteer": "^24.0.0",
- "supertest": "^7.2.2"
+ "supertest": "^7.2.2",
+ "tailwindcss": "^3.4.19"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz",
+ "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@babel/code-frame": {
@@ -617,2585 +636,4074 @@
"kuler": "^2.0.0"
}
},
- "node_modules/@emnapi/core": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
- "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
+ "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": "MIT",
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.1.0",
- "tslib": "^2.4.0"
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=22.12.0"
}
},
- "node_modules/@emnapi/runtime": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
- "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "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",
- "optional": true,
"dependencies": {
- "tslib": "^2.4.0"
+ "commander": "^5.0.0",
+ "glob": "^7.1.6",
+ "minimatch": "^3.0.4"
+ },
+ "bin": {
+ "asar": "bin/asar.js"
+ },
+ "engines": {
+ "node": ">=10.12.0"
}
},
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
- "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
+ "node_modules/@electron/asar/node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
+ "engines": {
+ "node": ">= 6"
}
},
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "node_modules/@electron/asar/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "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": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ "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": ">=12"
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "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",
- "engines": {
- "node": ">=12"
+ "dependencies": {
+ "chalk": "^4.1.1",
+ "fs-extra": "^9.0.1",
+ "minimist": "^1.2.5"
},
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ "bin": {
+ "electron-fuses": "dist/bin.js"
}
},
- "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "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",
- "engines": {
- "node": ">=12"
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
},
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@isaacs/cliui/node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "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": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
+ "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": ">=12"
+ "node": ">=22.12.0"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "optionalDependencies": {
+ "undici": "^7.24.4"
}
},
- "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
- "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
+ "node_modules/@electron/get/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-regex": "^6.0.1"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">=12"
+ "node": ">=6.0"
},
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "node_modules/@electron/get/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",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
"engines": {
- "node": ">=12"
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@istanbuljs/load-nyc-config": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
- "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "node_modules/@electron/get/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",
- "dependencies": {
- "camelcase": "^5.3.1",
- "find-up": "^4.1.0",
- "get-package-type": "^0.1.0",
- "js-yaml": "^3.13.1",
- "resolve-from": "^5.0.0"
+ "bin": {
+ "semver": "bin/semver.js"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
}
},
- "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "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": {
- "sprintf-js": "~1.0.2"
+ "debug": "^4.1.1",
+ "fs-extra": "^9.0.1",
+ "promise-retry": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
}
},
- "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
- "version": "3.14.2",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
- "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "node_modules/@electron/notarize/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
+ "ms": "^2.1.3"
},
- "bin": {
- "js-yaml": "bin/js-yaml.js"
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "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": ">=8"
+ "node": ">=10"
}
},
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
- "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "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/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
"engines": {
- "node": ">=8"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@jest/console": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz",
- "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==",
+ "node_modules/@electron/osx-sign/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.2.0",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "jest-message-util": "30.2.0",
- "jest-util": "30.2.0",
- "slash": "^3.0.0"
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
}
},
- "node_modules/@jest/core": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz",
- "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==",
+ "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.1",
+ "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-4.2.1.tgz",
+ "integrity": "sha512-IS4pG3BysRrCLJ8xTAfvg+IQDbiUoAzdJy2SfjcYKnLDy5DpCdjnPdhS5Zf5UMfrkB24xu0KC+TqcOxg+eG+6w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/console": "30.2.0",
- "@jest/pattern": "30.0.1",
- "@jest/reporters": "30.2.0",
- "@jest/test-result": "30.2.0",
- "@jest/transform": "30.2.0",
- "@jest/types": "30.2.0",
- "@types/node": "*",
- "ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "exit-x": "^0.2.2",
- "graceful-fs": "^4.2.11",
- "jest-changed-files": "30.2.0",
- "jest-config": "30.2.0",
- "jest-haste-map": "30.2.0",
- "jest-message-util": "30.2.0",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.2.0",
- "jest-resolve-dependencies": "30.2.0",
- "jest-runner": "30.2.0",
- "jest-runtime": "30.2.0",
- "jest-snapshot": "30.2.0",
- "jest-util": "30.2.0",
- "jest-validate": "30.2.0",
- "jest-watcher": "30.2.0",
- "micromatch": "^4.0.8",
- "pretty-format": "30.2.0",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "@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"
},
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ "bin": {
+ "electron-rebuild": "lib/cli.js"
},
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/@jest/diff-sequences": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
- "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
- "dev": true,
- "license": "MIT",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=22.12.0"
}
},
- "node_modules/@jest/environment": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz",
- "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==",
+ "node_modules/@electron/rebuild/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/fake-timers": "30.2.0",
- "@jest/types": "30.2.0",
- "@types/node": "*",
- "jest-mock": "30.2.0"
+ "ms": "^2.1.3"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@jest/expect": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz",
- "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==",
+ "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": {
- "expect": "30.2.0",
- "jest-snapshot": "30.2.0"
+ "@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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=16.4"
}
},
- "node_modules/@jest/expect-utils": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz",
- "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==",
+ "node_modules/@electron/universal/node_modules/brace-expansion": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
+ "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/get-type": "30.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/@jest/fake-timers": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz",
- "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==",
+ "node_modules/@electron/universal/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/types": "30.2.0",
- "@sinonjs/fake-timers": "^13.0.0",
- "@types/node": "*",
- "jest-message-util": "30.2.0",
- "jest-mock": "30.2.0",
- "jest-util": "30.2.0"
+ "ms": "^2.1.3"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/get-type": {
- "version": "30.1.0",
- "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
- "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/@jest/globals": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz",
- "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==",
+ "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": "MIT",
+ "license": "ISC",
"dependencies": {
- "@jest/environment": "30.2.0",
- "@jest/expect": "30.2.0",
- "@jest/types": "30.2.0",
- "jest-mock": "30.2.0"
+ "brace-expansion": "^2.0.2"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@jest/pattern": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
- "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
+ "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": "MIT",
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "peer": true,
"dependencies": {
- "@types/node": "*",
- "jest-regex-util": "30.0.1"
+ "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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=14.14"
}
},
- "node_modules/@jest/reporters": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz",
- "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==",
+ "node_modules/@electron/windows-sign/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"dependencies": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "30.2.0",
- "@jest/test-result": "30.2.0",
- "@jest/transform": "30.2.0",
- "@jest/types": "30.2.0",
- "@jridgewell/trace-mapping": "^0.3.25",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "collect-v8-coverage": "^1.0.2",
- "exit-x": "^0.2.2",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^6.0.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^5.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "30.2.0",
- "jest-util": "30.2.0",
- "jest-worker": "30.2.0",
- "slash": "^3.0.0",
- "string-length": "^4.0.2",
- "v8-to-istanbul": "^9.0.1"
+ "ms": "^2.1.3"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ "node": ">=6.0"
},
"peerDependenciesMeta": {
- "node-notifier": {
+ "supports-color": {
"optional": true
}
}
},
- "node_modules/@jest/schemas": {
- "version": "30.0.5",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
- "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
+ "node_modules/@emnapi/core": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
+ "integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
"dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@sinclair/typebox": "^0.34.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "@emnapi/wasi-threads": "1.1.0",
+ "tslib": "^2.4.0"
}
},
- "node_modules/@jest/snapshot-utils": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz",
- "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==",
+ "node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
+ "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
"dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@jest/types": "30.2.0",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "natural-compare": "^1.4.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "tslib": "^2.4.0"
}
},
- "node_modules/@jest/source-map": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
- "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
+ "node_modules/@emnapi/wasi-threads": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
+ "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
"dev": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.25",
- "callsites": "^3.1.0",
- "graceful-fs": "^4.2.11"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "tslib": "^2.4.0"
}
},
- "node_modules/@jest/test-result": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz",
- "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==",
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "@jest/console": "30.2.0",
- "@jest/types": "30.2.0",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "collect-v8-coverage": "^1.0.2"
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
}
},
- "node_modules/@jest/test-sequencer": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz",
- "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==",
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@jest/test-result": "30.2.0",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.2.0",
- "slash": "^3.0.0"
- },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
- "node_modules/@jest/transform": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz",
- "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==",
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@jest/types": "30.2.0",
- "@jridgewell/trace-mapping": "^0.3.25",
- "babel-plugin-istanbul": "^7.0.1",
- "chalk": "^4.1.2",
- "convert-source-map": "^2.0.0",
- "fast-json-stable-stringify": "^2.1.0",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.2.0",
- "jest-regex-util": "30.0.1",
- "jest-util": "30.2.0",
- "micromatch": "^4.0.8",
- "pirates": "^4.0.7",
- "slash": "^3.0.0",
- "write-file-atomic": "^5.0.1"
- },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/@jest/types": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz",
- "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==",
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/pattern": "30.0.1",
- "@jest/schemas": "30.0.5",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "@types/istanbul-reports": "^3.0.4",
- "@types/node": "*",
- "@types/yargs": "^17.0.33",
- "chalk": "^4.1.2"
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
- "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz",
+ "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
- "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "license": "MIT",
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
"engines": {
- "node": ">=6.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "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": "MIT",
+ "license": "ISC",
"dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
}
},
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "0.2.12",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
- "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
"dev": true,
- "license": "MIT",
- "optional": true,
+ "license": "ISC",
"dependencies": {
- "@emnapi/core": "^1.4.3",
- "@emnapi/runtime": "^1.4.3",
- "@tybys/wasm-util": "^0.10.0"
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": "^14.21.3 || >=16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
}
},
- "node_modules/@paralleldrive/cuid2": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
- "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@noble/hashes": "^1.1.5"
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"license": "MIT",
- "optional": true,
"engines": {
- "node": ">=14"
+ "node": ">=8"
}
},
- "node_modules/@pkgr/core": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
- "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/pkgr"
+ "node": ">=8"
}
},
- "node_modules/@puppeteer/browsers": {
- "version": "2.10.8",
- "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.8.tgz",
- "integrity": "sha512-f02QYEnBDE0p8cteNoPYHHjbDuwyfbe4cCIVlNi8/MRicIxFW4w4CfgU0LNgWEID6s06P+hRJ1qjpBLMhPRCiQ==",
+ "node_modules/@jest/console": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz",
+ "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"dependencies": {
- "debug": "^4.4.1",
- "extract-zip": "^2.0.1",
- "progress": "^2.0.3",
- "proxy-agent": "^6.5.0",
- "semver": "^7.7.2",
- "tar-fs": "^3.1.0",
- "yargs": "^17.7.2"
- },
- "bin": {
- "browsers": "lib/cjs/main-cli.js"
+ "@jest/types": "30.2.0",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "jest-message-util": "30.2.0",
+ "jest-util": "30.2.0",
+ "slash": "^3.0.0"
},
"engines": {
- "node": ">=18"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@puppeteer/browsers/node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "node_modules/@jest/core": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz",
+ "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
+ "@jest/console": "30.2.0",
+ "@jest/pattern": "30.0.1",
+ "@jest/reporters": "30.2.0",
+ "@jest/test-result": "30.2.0",
+ "@jest/transform": "30.2.0",
+ "@jest/types": "30.2.0",
+ "@types/node": "*",
+ "ansi-escapes": "^4.3.2",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "exit-x": "^0.2.2",
+ "graceful-fs": "^4.2.11",
+ "jest-changed-files": "30.2.0",
+ "jest-config": "30.2.0",
+ "jest-haste-map": "30.2.0",
+ "jest-message-util": "30.2.0",
+ "jest-regex-util": "30.0.1",
+ "jest-resolve": "30.2.0",
+ "jest-resolve-dependencies": "30.2.0",
+ "jest-runner": "30.2.0",
+ "jest-runtime": "30.2.0",
+ "jest-snapshot": "30.2.0",
+ "jest-util": "30.2.0",
+ "jest-validate": "30.2.0",
+ "jest-watcher": "30.2.0",
+ "micromatch": "^4.0.8",
+ "pretty-format": "30.2.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
"optional": true
}
}
},
- "node_modules/@puppeteer/browsers/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "node_modules/@jest/diff-sequences": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
+ "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
"dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@sinclair/typebox": {
- "version": "0.34.48",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz",
- "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@sinonjs/commons": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
- "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "node_modules/@jest/environment": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz",
+ "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==",
"dev": true,
- "license": "BSD-3-Clause",
+ "license": "MIT",
"dependencies": {
- "type-detect": "4.0.8"
+ "@jest/fake-timers": "30.2.0",
+ "@jest/types": "30.2.0",
+ "@types/node": "*",
+ "jest-mock": "30.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@sinonjs/fake-timers": {
- "version": "13.0.5",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
- "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
+ "node_modules/@jest/expect": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz",
+ "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==",
"dev": true,
- "license": "BSD-3-Clause",
+ "license": "MIT",
"dependencies": {
- "@sinonjs/commons": "^3.0.1"
+ "expect": "30.2.0",
+ "jest-snapshot": "30.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@socket.io/component-emitter": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
- "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@tootallnate/quickjs-emscripten": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
- "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
- "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "node_modules/@jest/expect-utils": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz",
+ "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==",
"dev": true,
"license": "MIT",
- "optional": true,
"dependencies": {
- "tslib": "^2.4.0"
+ "@jest/get-type": "30.1.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "node_modules/@jest/fake-timers": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz",
+ "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
+ "@jest/types": "30.2.0",
+ "@sinonjs/fake-timers": "^13.0.0",
+ "@types/node": "*",
+ "jest-message-util": "30.2.0",
+ "jest-mock": "30.2.0",
+ "jest-util": "30.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "node_modules/@jest/get-type": {
+ "version": "30.1.0",
+ "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz",
+ "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "node_modules/@jest/globals": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz",
+ "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
+ "@jest/environment": "30.2.0",
+ "@jest/expect": "30.2.0",
+ "@jest/types": "30.2.0",
+ "jest-mock": "30.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
- "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "node_modules/@jest/pattern": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
+ "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.2"
+ "@types/node": "*",
+ "jest-regex-util": "30.0.1"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/cors": {
- "version": "2.8.19",
- "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
- "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "node_modules/@jest/reporters": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz",
+ "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/node": "*"
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "30.2.0",
+ "@jest/test-result": "30.2.0",
+ "@jest/transform": "30.2.0",
+ "@jest/types": "30.2.0",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "@types/node": "*",
+ "chalk": "^4.1.2",
+ "collect-v8-coverage": "^1.0.2",
+ "exit-x": "^0.2.2",
+ "glob": "^10.3.10",
+ "graceful-fs": "^4.2.11",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^5.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "30.2.0",
+ "jest-util": "30.2.0",
+ "jest-worker": "30.2.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.2",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
- "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "node_modules/@jest/schemas": {
+ "version": "30.0.5",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz",
+ "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/istanbul-lib-coverage": "*"
+ "@sinclair/typebox": "^0.34.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
- "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "node_modules/@jest/snapshot-utils": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz",
+ "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "node_modules/@types/jest": {
- "version": "30.0.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
- "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
+ "@jest/types": "30.2.0",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "natural-compare": "^1.4.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "30.0.1",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
+ "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "expect": "^30.0.0",
- "pretty-format": "^30.0.0"
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "callsites": "^3.1.0",
+ "graceful-fs": "^4.2.11"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/node": {
- "version": "24.3.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz",
- "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
+ "node_modules/@jest/test-result": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz",
+ "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~7.10.0"
+ "@jest/console": "30.2.0",
+ "@jest/types": "30.2.0",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "collect-v8-coverage": "^1.0.2"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/stack-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "node_modules/@jest/test-sequencer": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz",
+ "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/@types/triple-beam": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
- "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@jest/test-result": "30.2.0",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.2.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
},
- "node_modules/@types/yargs": {
- "version": "17.0.35",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
- "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "node_modules/@jest/transform": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz",
+ "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@types/yargs-parser": "*"
+ "@babel/core": "^7.27.4",
+ "@jest/types": "30.2.0",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "babel-plugin-istanbul": "^7.0.1",
+ "chalk": "^4.1.2",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.11",
+ "jest-haste-map": "30.2.0",
+ "jest-regex-util": "30.0.1",
+ "jest-util": "30.2.0",
+ "micromatch": "^4.0.8",
+ "pirates": "^4.0.7",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^5.0.1"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
- "node_modules/@types/yargs-parser": {
- "version": "21.0.3",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "node_modules/@jest/types": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz",
+ "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@jest/pattern": "30.0.1",
+ "@jest/schemas": "30.0.5",
+ "@types/istanbul-lib-coverage": "^2.0.6",
+ "@types/istanbul-reports": "^3.0.4",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.33",
+ "chalk": "^4.1.2"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
},
- "node_modules/@types/yauzl": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
- "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT",
- "optional": true,
"dependencies": {
- "@types/node": "*"
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
}
},
- "node_modules/@ungap/structured-clone": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
- "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
"dev": true,
- "license": "ISC"
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
},
- "node_modules/@unrs/resolver-binding-android-arm-eabi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
- "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
+ "engines": {
+ "node": ">=6.0.0"
+ }
},
- "node_modules/@unrs/resolver-binding-android-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
- "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ]
+ "license": "MIT"
},
- "node_modules/@unrs/resolver-binding-darwin-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
- "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ]
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
},
- "node_modules/@unrs/resolver-binding-darwin-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
- "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
- "cpu": [
- "x64"
+ "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",
- "optional": true,
- "os": [
- "darwin"
- ]
+ "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/@unrs/resolver-binding-freebsd-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
- "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
- "cpu": [
- "x64"
- ],
+ "node_modules/@malept/flatpak-bundler/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ]
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
- "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
- "cpu": [
- "arm"
- ],
+ "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",
- "optional": true,
- "os": [
- "linux"
- ]
+ "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/@unrs/resolver-binding-linux-arm-musleabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
- "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@napi-rs/wasm-runtime": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
+ "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
"dev": true,
"license": "MIT",
"optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@emnapi/core": "^1.4.3",
+ "@emnapi/runtime": "^1.4.3",
+ "@tybys/wasm-util": "^0.10.0"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
- "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@noble/hashes": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
+ "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "engines": {
+ "node": "^14.21.3 || >=16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
- "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
- "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
- "cpu": [
- "ppc64"
- ],
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "engines": {
+ "node": ">= 8"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
- "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
- "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
- "cpu": [
- "riscv64"
- ],
+ "node_modules/@paralleldrive/cuid2": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz",
+ "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@noble/hashes": "^1.1.5"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
- "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
- "cpu": [
- "s390x"
- ],
+ "node_modules/@peculiar/asn1-schema": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.11.0.tgz",
+ "integrity": "sha512-8xh4avo53/vXO6UEv9yaoJ83hY581geaLTygf61NPIXP5AeIZCPjJhpTaYU23IZkG+NpLN/C9FYzWp7hphIT9A==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "@peculiar/utils": "^2.0.2",
+ "asn1js": "^3.0.10",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
- "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
- "cpu": [
- "x64"
- ],
+ "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",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
},
- "node_modules/@unrs/resolver-binding-linux-x64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
- "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
- "cpu": [
- "x64"
- ],
+ "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",
- "optional": true,
- "os": [
- "linux"
- ]
+ "dependencies": {
+ "tslib": "^2.8.1"
+ }
},
- "node_modules/@unrs/resolver-binding-wasm32-wasi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
- "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
- "cpu": [
- "wasm32"
- ],
+ "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/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
"license": "MIT",
"optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
+ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
+ "node_modules/@posthog/core": {
+ "version": "1.59.3",
+ "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.59.3.tgz",
+ "integrity": "sha512-XbfpD82YSms/asHU44xQq5vqadi6rHTRg6fyoTqjdGTiC1NiPRCeO8xhtANT682BkvlKJo+JwRDBu3Q8oEqQpw==",
+ "license": "MIT",
"dependencies": {
- "@napi-rs/wasm-runtime": "^0.2.11"
+ "@posthog/types": "^1.416.0"
+ }
+ },
+ "node_modules/@posthog/types": {
+ "version": "1.416.0",
+ "resolved": "https://registry.npmjs.org/@posthog/types/-/types-1.416.0.tgz",
+ "integrity": "sha512-0/9+02s/0uDyrH4G/qUg1yyl6gXUg8Uuxw/PlDad3KLzo9FFS9zS/kAQaEshx/saVGupj1aAy/4EUBxWisBogw==",
+ "license": "MIT"
+ },
+ "node_modules/@puppeteer/browsers": {
+ "version": "2.10.8",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.8.tgz",
+ "integrity": "sha512-f02QYEnBDE0p8cteNoPYHHjbDuwyfbe4cCIVlNi8/MRicIxFW4w4CfgU0LNgWEID6s06P+hRJ1qjpBLMhPRCiQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "debug": "^4.4.1",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.5.0",
+ "semver": "^7.7.2",
+ "tar-fs": "^3.1.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
},
"engines": {
- "node": ">=14.0.0"
+ "node": ">=18"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.34.48",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz",
+ "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "13.0.5",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
+ "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.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/@tailwindcss/container-queries": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz",
+ "integrity": "sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "tailwindcss": ">=3.2.0"
+ }
+ },
+ "node_modules/@tailwindcss/forms": {
+ "version": "0.5.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.11.tgz",
+ "integrity": "sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mini-svg-data-uri": "^1.2.3"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
+ }
+ },
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@tybys/wasm-util": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
+ "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+ "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+ "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.2"
+ }
+ },
+ "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/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "30.0.0",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
+ "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^30.0.0",
+ "pretty-format": "^30.0.0"
+ }
+ },
+ "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.19.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz",
+ "integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": ">=7.24.0 <7.24.7"
+ }
+ },
+ "node_modules/@types/responselike": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
+ "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
+ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@unrs/resolver-binding-android-arm-eabi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
+ "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-android-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
+ "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-arm64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
+ "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-darwin-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
+ "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-freebsd-x64": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
+ "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
+ "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
+ "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
+ "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
+ "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
+ "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
+ "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
+ "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
+ "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
+ "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-linux-x64-musl": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
+ "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-wasm32-wasi": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
+ "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@napi-rs/wasm-runtime": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
+ "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
+ "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
+ "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@xmldom/xmldom": {
+ "version": "0.8.15",
+ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz",
+ "integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==",
+ "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/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "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-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles/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==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/ansi-styles/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==",
+ "license": "MIT"
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/app-builder-lib": {
+ "version": "26.18.0",
+ "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.18.0.tgz",
+ "integrity": "sha512-lx+KkuCSZHcbECf4R3IAcC9VOFk0+cMUwljO63s5y8yqS1Lw0sRGmjPaWsPwP3zv3ohZYbMhUvjXeiQXXZhJXA==",
+ "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.2.1",
+ "@electron/universal": "2.0.3",
+ "@malept/flatpak-bundler": "^0.4.0",
+ "@noble/hashes": "^1.8.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.16.0",
+ "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.18.0",
+ "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.18.0",
+ "electron-builder-squirrel-windows": "26.18.0"
+ }
+ },
+ "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/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/@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/@electron/get/node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/app-builder-lib/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/app-builder-lib/node_modules/brace-expansion": {
+ "version": "5.0.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^4.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ }
+ },
+ "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/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/app-builder-lib/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/app-builder-lib/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/app-builder-lib/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/app-builder-lib/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/app-builder-lib/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/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/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/append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
+ "license": "MIT"
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/asn1js": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.1.0.tgz",
+ "integrity": "sha512-HWYi1THkOqguCiO+vwj09ZkQFD2kKEsejYHAYCtX0D80WVdoDnvRc9IukXX/jeb0T9NRWJnRtqwdbHltnFjwXA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.2.0",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "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/b4a": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
+ "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/babel-jest": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz",
+ "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/transform": "30.2.0",
+ "@types/babel__core": "^7.20.5",
+ "babel-plugin-istanbul": "^7.0.1",
+ "babel-preset-jest": "30.2.0",
+ "chalk": "^4.1.2",
+ "graceful-fs": "^4.2.11",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz",
+ "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "workspaces": [
+ "test/babel-8"
+ ],
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-instrument": "^6.0.2",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz",
+ "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/babel__core": "^7.20.5"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ }
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
+ "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0 || ^8.0.0-0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "30.2.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz",
+ "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "babel-plugin-jest-hoist": "30.2.0",
+ "babel-preset-current-node-syntax": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0 || ^8.0.0-beta.1"
+ }
+ },
+ "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/bare-events": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.1.tgz",
+ "integrity": "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true
+ },
+ "node_modules/bare-fs": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.2.3.tgz",
+ "integrity": "sha512-1aGs5pRVLToMQ79elP+7cc0u0s/wXAzfBv/7hDloT7WFggLqECCas5qqPky7WHCFdsBH5WDq6sD4fAoz5sJbtA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "bare-events": "^2.5.4",
+ "bare-path": "^3.0.0",
+ "bare-stream": "^2.6.4"
+ },
+ "engines": {
+ "bare": ">=1.16.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/bare-os": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz",
+ "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "engines": {
+ "bare": ">=1.14.0"
+ }
+ },
+ "node_modules/bare-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
+ "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "bare-os": "^3.0.1"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz",
+ "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "streamx": "^2.21.0"
+ },
+ "peerDependencies": {
+ "bare-buffer": "*",
+ "bare-events": "*"
+ },
+ "peerDependenciesMeta": {
+ "bare-buffer": {
+ "optional": true
+ },
+ "bare-events": {
+ "optional": true
+ }
+ }
+ },
+ "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/baseline-browser-mapping": {
+ "version": "2.9.19",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
+ "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
}
},
- "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
- "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
- "cpu": [
- "arm64"
- ],
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "engines": {
+ "node": ">=10.0.0"
+ }
},
- "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
- "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
- "cpu": [
- "ia32"
- ],
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ]
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
- "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
- "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
- "cpu": [
- "x64"
- ],
+ "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",
- "optional": true,
- "os": [
- "win32"
- ]
+ "license": "MIT"
},
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
"license": "MIT",
"dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
+ "bytes": "3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
}
},
- "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,
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"license": "MIT",
- "engines": {
- "node": ">= 14"
+ "dependencies": {
+ "ms": "2.0.0"
}
},
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
- "license": "MIT",
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/body-parser/node_modules/qs": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "license": "BSD-3-Clause",
"dependencies": {
- "type-fest": "^0.21.3"
+ "side-channel": "^1.0.6"
},
"engines": {
- "node": ">=8"
+ "node": ">=0.6"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "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==",
+ "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",
- "engines": {
- "node": ">=8"
+ "optional": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "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==",
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/ansi-styles/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==",
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
"dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "color-name": "~1.1.4"
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
},
"engines": {
- "node": ">=7.0.0"
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/ansi-styles/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==",
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
"dev": true,
- "license": "MIT"
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
},
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 8"
+ "node": "*"
}
},
- "node_modules/append-field": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
- "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
- "license": "MIT"
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
},
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "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==",
"license": "MIT"
},
- "node_modules/asap": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
- "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
+ "node_modules/builder-util": {
+ "version": "26.16.0",
+ "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.16.0.tgz",
+ "integrity": "sha512-RLyJhB7Si3YkzKR9ubQslWuXW3Vhs3CGe1i+SeixBZ0qTd1mk3XBmssvY22TlB6CS5blyko8Gu1JzpYk8UkYAg==",
"dev": true,
- "license": "MIT"
+ "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/ast-types": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
- "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "node_modules/builder-util-runtime": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz",
+ "integrity": "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tslib": "^2.0.1"
+ "debug": "^4.3.4",
+ "sax": "^1.2.4"
},
"engines": {
- "node": ">=4"
+ "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==",
- "license": "MIT"
- },
- "node_modules/async-each-series": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
- "integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==",
+ "node_modules/builder-util-runtime/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
"engines": {
- "node": ">=0.8.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "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/b4a": {
- "version": "1.6.7",
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
- "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/babel-jest": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.2.0.tgz",
- "integrity": "sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw==",
+ "node_modules/builder-util/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/transform": "30.2.0",
- "@types/babel__core": "^7.20.5",
- "babel-plugin-istanbul": "^7.0.1",
- "babel-preset-jest": "30.2.0",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "slash": "^3.0.0"
+ "ms": "^2.1.3"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=6.0"
},
- "peerDependencies": {
- "@babel/core": "^7.11.0 || ^8.0.0-0"
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/babel-plugin-istanbul": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz",
- "integrity": "sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA==",
+ "node_modules/builder-util/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
- "license": "BSD-3-Clause",
- "workspaces": [
- "test/babel-8"
- ],
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@istanbuljs/load-nyc-config": "^1.0.0",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-instrument": "^6.0.2",
- "test-exclude": "^6.0.0"
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
},
"engines": {
"node": ">=12"
}
},
- "node_modules/babel-plugin-jest-hoist": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz",
- "integrity": "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA==",
+ "node_modules/builder-util/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": {
- "@types/babel__core": "^7.20.5"
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=10.16.0"
}
},
- "node_modules/babel-preset-current-node-syntax": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
- "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==",
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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",
- "dependencies": {
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-bigint": "^7.8.3",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-import-attributes": "^7.24.7",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0 || ^8.0.0-0"
+ "engines": {
+ "node": ">=10.6.0"
}
},
- "node_modules/babel-preset-jest": {
- "version": "30.2.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz",
- "integrity": "sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ==",
+ "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": {
- "babel-plugin-jest-hoist": "30.2.0",
- "babel-preset-current-node-syntax": "^1.2.0"
+ "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": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.11.0 || ^8.0.0-beta.1"
+ "node": ">=8"
}
},
- "node_modules/balanced-match": {
+ "node_modules/call-bind-apply-helpers": {
"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/bare-events": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.6.1.tgz",
- "integrity": "sha512-AuTJkq9XmE6Vk0FJVNq5QxETrSA/vKHarWVBG5l/JbdCL1prJemiyJqUS0jrlXO0MftuPq4m3YVYhoNc5+aE/g==",
- "dev": true,
- "license": "Apache-2.0",
- "optional": true
- },
- "node_modules/bare-fs": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.2.3.tgz",
- "integrity": "sha512-1aGs5pRVLToMQ79elP+7cc0u0s/wXAzfBv/7hDloT7WFggLqECCas5qqPky7WHCFdsBH5WDq6sD4fAoz5sJbtA==",
- "dev": true,
- "license": "Apache-2.0",
- "optional": true,
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
"dependencies": {
- "bare-events": "^2.5.4",
- "bare-path": "^3.0.0",
- "bare-stream": "^2.6.4"
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
},
"engines": {
- "bare": ">=1.16.0"
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
},
- "peerDependencies": {
- "bare-buffer": "*"
+ "engines": {
+ "node": ">= 0.4"
},
- "peerDependenciesMeta": {
- "bare-buffer": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/bare-os": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.6.2.tgz",
- "integrity": "sha512-T+V1+1srU2qYNBmJCXZkUY5vQ0B4FSlL3QDROnKQYOqeiQR8UbjNHlPa+TIbM4cuidiN9GaTaOZgSEgsvPbh5A==",
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
- "license": "Apache-2.0",
- "optional": true,
+ "license": "MIT",
"engines": {
- "bare": ">=1.14.0"
+ "node": ">=6"
}
},
- "node_modules/bare-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz",
- "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==",
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true,
- "license": "Apache-2.0",
- "optional": true,
- "dependencies": {
- "bare-os": "^3.0.1"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
}
},
- "node_modules/bare-stream": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.7.0.tgz",
- "integrity": "sha512-oyXQNicV1y8nc2aKffH+BUHFRXmx6VrPzlnaEvMhram0nPBrKcEdcyBg5r08D0i8VxngHFAiVyn1QKXpSG0B8A==",
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001766",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
+ "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "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": "Apache-2.0",
- "optional": true,
+ "license": "MIT",
"dependencies": {
- "streamx": "^2.21.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
- "peerDependencies": {
- "bare-buffer": "*",
- "bare-events": "*"
+ "engines": {
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "bare-buffer": {
- "optional": true
- },
- "bare-events": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/base64id": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
- "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==",
+ "node_modules/chalk/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": "^4.5.0 || >= 5.9"
+ "node": ">=8"
}
},
- "node_modules/baseline-browser-mapping": {
- "version": "2.9.19",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
- "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
+ "node_modules/chalk/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": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.js"
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/basic-ftp": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
- "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=10.0.0"
+ "node": ">=10"
}
},
- "node_modules/batch": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
- "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
"engines": {
- "node": ">=8"
+ "node": ">= 8.10.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
}
},
- "node_modules/body-parser": {
- "version": "1.20.3",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
- "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
- "license": "MIT",
+ "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-bidi": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-8.0.0.tgz",
+ "integrity": "sha512-d1VmE0FD7lxZQHzcDUCKZSNRtRwISXDsdg4HjdTR5+Ll5nQ/vzU12JeNmupD6VWffrPSlrnGhEWlLESKH3VO+g==",
+ "dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.5",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.13.0",
- "raw-body": "2.5.2",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
+ "mitt": "^3.0.1",
+ "zod": "^3.24.1"
},
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "peerDependencies": {
+ "devtools-protocol": "*"
}
},
- "node_modules/body-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "node_modules/chromium-bidi/node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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",
- "dependencies": {
- "ms": "2.0.0"
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/body-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "node_modules/cjs-module-lexer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
+ "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==",
+ "dev": true,
"license": "MIT"
},
- "node_modules/body-parser/node_modules/qs": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
- "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
- "license": "BSD-3-Clause",
+ "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": {
- "side-channel": "^1.0.6"
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
},
"engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=12"
}
},
- "node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "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": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "mimic-response": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
"engines": {
- "node": ">=8"
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
}
},
- "node_modules/browser-sync": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-3.0.4.tgz",
- "integrity": "sha512-mcYOIy4BW6sWSEnTSBjQwWsnbx2btZX78ajTTjdNfyC/EqQVcIe0nQR6894RNAMtvlfAnLaH9L2ka97zpvgenA==",
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
+ "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT"
+ },
+ "node_modules/color": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
+ "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
+ "license": "MIT",
"dependencies": {
- "browser-sync-client": "^3.0.4",
- "browser-sync-ui": "^3.0.4",
- "bs-recipes": "1.3.4",
- "chalk": "4.1.2",
- "chokidar": "^3.5.1",
- "connect": "3.6.6",
- "connect-history-api-fallback": "^1",
- "dev-ip": "^1.0.1",
- "easy-extender": "^2.3.4",
- "eazy-logger": "^4.1.0",
- "etag": "^1.8.1",
- "fresh": "^0.5.2",
- "fs-extra": "3.0.1",
- "http-proxy": "^1.18.1",
- "immutable": "^3",
- "micromatch": "^4.0.8",
- "opn": "5.3.0",
- "portscanner": "2.2.0",
- "raw-body": "^2.3.2",
- "resp-modifier": "6.0.2",
- "rx": "4.1.0",
- "send": "^0.19.0",
- "serve-index": "^1.9.1",
- "serve-static": "^1.16.2",
- "server-destroy": "1.0.1",
- "socket.io": "^4.4.1",
- "ua-parser-js": "^1.0.33",
- "yargs": "^17.3.1"
- },
- "bin": {
- "browser-sync": "dist/bin.js"
- },
- "engines": {
- "node": ">= 8.0.0"
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
}
},
- "node_modules/browser-sync-client": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-3.0.4.tgz",
- "integrity": "sha512-+ew5ubXzGRKVjquBL3u6najS40TG7GxCdyBll0qSRc/n+JRV9gb/yDdRL1IAgRHqjnJTdqeBKKIQabjvjRSYRQ==",
- "dev": true,
- "license": "ISC",
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "license": "MIT",
"dependencies": {
- "etag": "1.8.1",
- "fresh": "0.5.2",
- "mitt": "^1.1.3"
- },
- "engines": {
- "node": ">=8.0.0"
+ "color-name": "1.1.3"
}
},
- "node_modules/browser-sync-ui": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-3.0.4.tgz",
- "integrity": "sha512-5Po3YARCZ/8yQHFzvrSjn8+hBUF7ZWac39SHsy8Tls+7tE62iq6pYWxpVU6aOOMAGD21RwFQhQeqmJPf70kHEQ==",
- "dev": true,
- "license": "Apache-2.0",
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "license": "MIT"
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "license": "MIT",
"dependencies": {
- "async-each-series": "0.1.1",
- "chalk": "4.1.2",
- "connect-history-api-fallback": "^1",
- "immutable": "^3",
- "server-destroy": "1.0.1",
- "socket.io-client": "^4.4.1",
- "stream-throttle": "^0.1.3"
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
}
},
- "node_modules/browser-sync/node_modules/fs-extra": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz",
- "integrity": "sha512-V3Z3WZWVUYd8hoCL5xfXJCaHWYzmtwW5XWYSlLgERi8PWd8bx1kUHUk8L1BT57e49oKnDDD180mjfrHc1yA9rg==",
- "dev": true,
+ "node_modules/colorspace": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
+ "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
"license": "MIT",
"dependencies": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^3.0.0",
- "universalify": "^0.1.0"
+ "color": "^3.1.3",
+ "text-hex": "1.0.x"
}
},
- "node_modules/browser-sync/node_modules/jsonfile": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz",
- "integrity": "sha512-oBko6ZHlubVB5mRFkur5vgYR1UyqX+S6Y/oCfLhqNdcc2fYFlDpIoNc7AfKS1KOGcnNAkvsr0grLck9ANM815w==",
+ "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",
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/browser-sync/node_modules/universalify": {
+ "node_modules/compare-version": {
"version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "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": ">= 4.0.0"
+ "node": ">=0.10.0"
}
},
- "node_modules/browserslist": {
- "version": "4.28.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
- "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "node_modules/component-emitter": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+ "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
"license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.9.0",
- "caniuse-lite": "^1.0.30001759",
- "electron-to-chromium": "^1.5.263",
- "node-releases": "^2.0.27",
- "update-browserslist-db": "^1.2.0"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/bs-recipes": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/bs-recipes/-/bs-recipes-1.3.4.tgz",
- "integrity": "sha512-BXvDkqhDNxXEjeGM8LFkSbR+jzmP/CYpCiVKYn+soB1dDldeU15EBNDkwVXndKuX35wnNUaPd0qSoQEAkmQtMw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/bser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
- "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "node-int64": "^0.4.0"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "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",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "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==",
"license": "MIT"
},
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
- "engines": {
- "node": ">=10.16.0"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "node_modules/concat-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
+ "engines": [
+ "node >= 6.0"
+ ],
"license": "MIT",
- "engines": {
- "node": ">= 0.8"
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.0.2",
+ "typedarray": "^0.0.6"
}
},
- "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==",
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"license": "MIT",
"dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
+ "safe-buffer": "5.2.1"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">= 0.6"
}
},
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">= 0.6"
}
},
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
"license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">= 0.6"
}
},
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/cookiejar": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
+ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
+ "license": "MIT"
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001766",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
- "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
+ "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,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
+ "license": "MIT"
},
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+ "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=14"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
- "node_modules/chalk/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==",
+ "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",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/chalk/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==",
+ "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": {
- "has-flag": "^4.0.0"
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
},
"engines": {
- "node": ">=8"
+ "node": ">= 8"
}
},
- "node_modules/char-regex": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
- "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true,
"license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=4"
}
},
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
"license": "MIT",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
"engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
+ "node": ">= 12"
}
},
- "node_modules/chromium-bidi": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-8.0.0.tgz",
- "integrity": "sha512-d1VmE0FD7lxZQHzcDUCKZSNRtRwISXDsdg4HjdTR5+Ll5nQ/vzU12JeNmupD6VWffrPSlrnGhEWlLESKH3VO+g==",
+ "node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
- "license": "Apache-2.0",
+ "license": "MIT",
"dependencies": {
- "mitt": "^3.0.1",
- "zod": "^3.24.1"
- },
- "peerDependencies": {
- "devtools-protocol": "*"
+ "ms": "^2.1.1"
}
},
- "node_modules/chromium-bidi/node_modules/mitt": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
- "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
- "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"
- }
- ],
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
- "node_modules/cjs-module-lexer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz",
- "integrity": "sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==",
- "dev": true,
- "license": "MIT"
- },
- "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==",
+ "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": "ISC",
+ "license": "MIT",
"dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
+ "mimic-response": "^3.1.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "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": {
- "iojs": ">= 1.0.0",
- "node": ">= 0.12.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/collect-v8-coverage": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
- "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==",
+ "node_modules/dedent": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
+ "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==",
"dev": true,
- "license": "MIT"
- },
- "node_modules/color": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
- "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
"license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.3",
- "color-string": "^1.6.0"
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
}
},
- "node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
"license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "license": "MIT"
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
- "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "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",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/colorspace": {
+ "node_modules/define-data-property": {
"version": "1.1.4",
- "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
- "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
+ "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": {
- "color": "^3.1.3",
- "text-hex": "1.0.x"
+ "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/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "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": {
- "delayed-stream": "~1.0.0"
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
},
"engines": {
- "node": ">= 0.8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/component-emitter": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
- "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
"dev": true,
"license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
}
},
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "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"
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
},
- "node_modules/concat-stream": {
+ "node_modules/depd": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
- "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
- "engines": [
- "node >= 6.0"
- ],
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.0.2",
- "typedarray": "^0.0.6"
+ "engines": {
+ "node": ">= 0.8"
}
},
- "node_modules/connect": {
- "version": "3.6.6",
- "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz",
- "integrity": "sha512-OO7axMmPpu/2XuX1+2Yrg0ddju31B6xLZMWkJ5rYBu4YRmRVlOjvlY6kw2FJKiAzyxGwnrDUAG4s1Pf0sbBMCQ==",
- "dev": true,
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "finalhandler": "1.1.0",
- "parseurl": "~1.3.2",
- "utils-merge": "1.0.1"
- },
"engines": {
- "node": ">= 0.10.0"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
}
},
- "node_modules/connect-history-api-fallback": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
- "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=0.8"
+ "node": ">=8"
}
},
- "node_modules/connect/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "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",
- "dependencies": {
- "ms": "2.0.0"
- }
+ "optional": true
},
- "node_modules/connect/node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "node_modules/devtools-protocol": {
+ "version": "0.0.1495869",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1495869.tgz",
+ "integrity": "sha512-i+bkd9UYFis40RcnkW7XrOprCujXRAHg62IVh/Ah3G8MmNXpCGt1m0dTFhSdx/AVs8XEMbdOGRwdkR1Bcta8AA==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
+ "license": "BSD-3-Clause"
},
- "node_modules/connect/node_modules/finalhandler": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
- "integrity": "sha512-ejnvM9ZXYzp6PUPUyQBMBf0Co5VX2gr5H2VQe2Ui2jWXNlxv+PYZo8wpAymJNJdLsG1R4p+M4aynF8KuoUEwRw==",
+ "node_modules/dezalgo": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
+ "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dev": true,
- "license": "MIT",
+ "license": "ISC",
"dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.1",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.2",
- "statuses": "~1.3.1",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
+ "asap": "^2.0.0",
+ "wrappy": "1"
}
},
- "node_modules/connect/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/dijkstrajs": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+ "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
"license": "MIT"
},
- "node_modules/connect/node_modules/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "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": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
+ "minimatch": "^3.0.5",
+ "p-limit": "^3.1.0 "
}
},
- "node_modules/connect/node_modules/statuses": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
- "integrity": "sha512-wuTCPGlJONk/a1kqZ4fQM2+908lC7fa7nPYpTC1EhnvqLX/IICbeP1OZGDtA374trpSq68YubKUMo8oRhN46yg==",
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
+ "license": "MIT"
},
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "node_modules/dmg-builder": {
+ "version": "26.18.0",
+ "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.18.0.tgz",
+ "integrity": "sha512-ozCGC54wi2C1RkS2v69y9lQxvoQ1Coh+iT8CmWiyY8y1ZuOKVvuNson2Hd+HEOs9+EZNNsOBbzKgQZ4SNqWd0w==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
+ "app-builder-lib": "26.18.0",
+ "builder-util": "26.16.0",
+ "fs-extra": "^10.1.0",
+ "js-yaml": "^4.1.0"
}
},
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "node_modules/dmg-builder/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
"engines": {
- "node": ">= 0.6"
+ "node": ">=12"
}
},
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cookie": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
- "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
- "license": "MIT",
+ "node_modules/dotenv": {
+ "version": "17.2.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
+ "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==",
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">= 0.6"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
}
},
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
- "node_modules/cookiejar": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
- "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cors": {
- "version": "2.8.5",
- "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
- "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "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": "MIT",
+ "license": "BSD-2-Clause",
"dependencies": {
- "object-assign": "^4",
- "vary": "^1"
+ "dotenv": "^16.4.5"
},
"engines": {
- "node": ">= 0.10"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
}
},
- "node_modules/cosmiconfig": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
- "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+ "node_modules/dotenv-expand/node_modules/dotenv": {
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "env-paths": "^2.2.1",
- "import-fresh": "^3.3.0",
- "js-yaml": "^4.1.0",
- "parse-json": "^5.2.0"
- },
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=14"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sponsors/d-fischer"
- },
- "peerDependencies": {
- "typescript": ">=4.9.5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "url": "https://dotenvx.com"
}
},
- "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,
+ "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==",
"license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
},
"engines": {
- "node": ">= 8"
+ "node": ">= 0.4"
}
},
- "node_modules/data-uri-to-buffer": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
- "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 12"
+ "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/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "node_modules/duplexer2/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": {
- "ms": "^2.1.1"
+ "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/dedent": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
- "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==",
+ "node_modules/duplexer2/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/duplexer2/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",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "optional": true
- }
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
}
},
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
}
},
- "node_modules/degenerator": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
- "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "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": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "ast-types": "^0.13.4",
- "escodegen": "^2.1.0",
- "esprima": "^4.0.1"
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
},
"engines": {
- "node": ">= 14"
+ "node": ">=0.10.0"
}
},
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "node_modules/electron": {
+ "version": "45.0.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-45.0.0.tgz",
+ "integrity": "sha512-yjz4uhMBcO6L5X7CWgRMobf2EMJPnb9j4zuf+nu/TU/6E4Sqfx7fn/a2eACo4qngjml/0JnsoZhxYroJLxLd2w==",
"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": ">=0.4.0"
+ "node": ">= 22.12.0"
}
},
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "node_modules/electron-builder": {
+ "version": "26.18.0",
+ "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.18.0.tgz",
+ "integrity": "sha512-ASgIuQnOq4RuD8jMhS9hI0LS3EMRT1I/M5R6utqifB/BHN80IcCjBdt+DED+NmNPvmBgEtrlExXZitNdA7kXOg==",
+ "dev": true,
"license": "MIT",
+ "dependencies": {
+ "app-builder-lib": "26.18.0",
+ "builder-util": "26.16.0",
+ "builder-util-runtime": "9.7.0",
+ "chalk": "^4.1.2",
+ "ci-info": "^4.2.0",
+ "dmg-builder": "26.18.0",
+ "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": ">= 0.8"
+ "node": ">=14.0.0"
}
},
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "node_modules/electron-builder-squirrel-windows": {
+ "version": "26.18.0",
+ "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.18.0.tgz",
+ "integrity": "sha512-a2elgTipboXNIsxqS1HOmHMGp4Pd3LJgIZOdIFTOskBSawvxKyZWYWQ1d7KKA4CtINSchYCYEKzhxRqiKZev9Q==",
+ "dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
+ "peer": true,
+ "dependencies": {
+ "app-builder-lib": "26.18.0",
+ "builder-util": "26.16.0",
+ "electron-winstaller": "5.4.0"
}
},
- "node_modules/detect-newline": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
- "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "node_modules/electron-builder/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
"engines": {
- "node": ">=8"
+ "node": ">=12"
}
},
- "node_modules/dev-ip": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz",
- "integrity": "sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==",
+ "node_modules/electron-builder/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": {
- "dev-ip": "lib/dev-ip.js"
+ "semver": "bin/semver.js"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=10"
}
},
- "node_modules/devtools-protocol": {
- "version": "0.0.1495869",
- "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1495869.tgz",
- "integrity": "sha512-i+bkd9UYFis40RcnkW7XrOprCujXRAHg62IVh/Ah3G8MmNXpCGt1m0dTFhSdx/AVs8XEMbdOGRwdkR1Bcta8AA==",
- "dev": true,
- "license": "BSD-3-Clause"
- },
- "node_modules/dezalgo": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
- "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
+ "node_modules/electron-builder/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": "ISC",
+ "license": "MIT",
"dependencies": {
- "asap": "^2.0.0",
- "wrappy": "1"
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "node_modules/dotenv": {
- "version": "17.2.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
- "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
+ "node_modules/electron-publish": {
+ "version": "26.18.0",
+ "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.18.0.tgz",
+ "integrity": "sha512-MagnqaZSALSWjcdKu5HEVhYUZD/2BDL3q7XzrqWwub6gf/UfD3ItMgmthVDv9w5y9E0gH1C3JWqKaXwf6f4ROg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/fs-extra": "^9.0.11",
+ "aws4": "^1.13.2",
+ "builder-util": "26.16.0",
+ "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/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "node_modules/electron-publish/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
},
"engines": {
- "node": ">= 0.4"
+ "node": ">=12"
}
},
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.283",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz",
+ "integrity": "sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==",
"dev": true,
- "license": "MIT"
+ "license": "ISC"
},
- "node_modules/easy-extender": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz",
- "integrity": "sha512-8cAwm6md1YTiPpOvDULYJL4ZS6WfM5/cTeVVh4JsvyYZAoqlRVUpHL9Gr5Fy7HA6xcSZicUia3DeAgO3Us8E+Q==",
+ "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": {
- "lodash": "^4.17.10"
+ "@electron/asar": "^3.2.1",
+ "debug": "^4.1.1",
+ "fs-extra": "^7.0.1",
+ "lodash": "^4.17.21",
+ "temp": "^0.9.0"
},
"engines": {
- "node": ">= 4.0.0"
+ "node": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@electron/windows-sign": "^1.1.2"
}
},
- "node_modules/eazy-logger": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/eazy-logger/-/eazy-logger-4.1.0.tgz",
- "integrity": "sha512-+mn7lRm+Zf1UT/YaH8WXtpU6PIV2iOjzP6jgKoiaq/VNrjYKp+OHZGe2znaLgDeFkw8cL9ffuaUm+nNnzcYyGw==",
+ "node_modules/electron-winstaller/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "chalk": "4.1.2"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
+ "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": {
- "safe-buffer": "^5.0.1"
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
}
},
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
+ "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-to-chromium": {
- "version": "1.5.283",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.283.tgz",
- "integrity": "sha512-3vifjt1HgrGW/h76UEeny+adYApveS9dH2h3p57JYzBSXJIKUJAvtmIytDKjcSCt9xHfrNCFJ7gts6vkhuq++w==",
+ "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": "ISC"
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
},
"node_modules/emittery": {
"version": "0.13.1",
@@ -3214,7 +4722,6 @@
"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/enabled": {
@@ -3242,97 +4749,6 @@
"once": "^1.4.0"
}
},
- "node_modules/engine.io": {
- "version": "6.6.4",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.4.tgz",
- "integrity": "sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/cors": "^2.8.12",
- "@types/node": ">=10.0.0",
- "accepts": "~1.3.4",
- "base64id": "2.0.0",
- "cookie": "~0.7.2",
- "cors": "~2.8.5",
- "debug": "~4.3.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.17.1"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/engine.io-client": {
- "version": "6.6.3",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
- "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1",
- "engine.io-parser": "~5.2.1",
- "ws": "~8.17.1",
- "xmlhttprequest-ssl": "~2.1.1"
- }
- },
- "node_modules/engine.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/engine.io-parser": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
- "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/engine.io/node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/engine.io/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
"node_modules/env-paths": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
@@ -3343,6 +4759,13 @@
"node": ">=6"
}
},
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -3406,6 +4829,14 @@
"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",
@@ -3497,13 +4928,6 @@
"node": ">= 0.6"
}
},
- "node_modules/eventemitter3": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/execa": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -3576,6 +5000,13 @@
"node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
}
},
+ "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/express": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
@@ -3691,6 +5122,13 @@
}
}
},
+ "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-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -3698,6 +5136,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -3712,6 +5167,33 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-uri": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz",
+ "integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastq": {
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz",
+ "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
"node_modules/fb-watchman": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
@@ -3767,7 +5249,40 @@
"integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==",
"license": "MIT",
"dependencies": {
- "moment": "^2.29.1"
+ "moment": "^2.29.1"
+ }
+ },
+ "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/brace-expansion": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz",
+ "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==",
+ "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/fill-range": {
@@ -3820,7 +5335,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"locate-path": "^5.0.0",
@@ -3836,27 +5350,6 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==",
"license": "MIT"
},
- "node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
"node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
@@ -3998,7 +5491,6 @@
"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.*"
@@ -4170,6 +5662,57 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/global-agent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
+ "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "dependencies": {
+ "boolean": "^3.0.1",
+ "es6-error": "^4.1.1",
+ "matcher": "^3.0.0",
+ "roarr": "^2.15.3",
+ "semver": "^7.3.2",
+ "serialize-error": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=10.0"
+ }
+ },
+ "node_modules/global-agent/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",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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",
@@ -4182,6 +5725,32 @@
"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",
@@ -4198,6 +5767,20 @@
"node": ">=4"
}
},
+ "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",
@@ -4227,9 +5810,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "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==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -4238,6 +5821,39 @@
"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/hosted-git-info/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/hosted-git-info/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/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -4245,6 +5861,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/http-cache-semantics": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.3.0.tgz",
+ "integrity": "sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -4261,21 +5884,6 @@
"node": ">= 0.8"
}
},
- "node_modules/http-proxy": {
- "version": "1.18.1",
- "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
- "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eventemitter3": "^4.0.0",
- "follow-redirects": "^1.0.0",
- "requires-port": "^1.0.0"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
@@ -4308,6 +5916,20 @@
}
}
},
+ "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",
@@ -4369,16 +5991,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/immutable": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
- "integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -4482,6 +6094,22 @@
"node": ">=8"
}
},
+ "node_modules/is-core-module": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz",
+ "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -4496,7 +6124,6 @@
"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"
@@ -4535,16 +6162,6 @@
"node": ">=0.12.0"
}
},
- "node_modules/is-number-like": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz",
- "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "lodash.isfinite": "^3.3.2"
- }
- },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -4557,14 +6174,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
+ "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": ">=4"
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/gjtorikian/"
}
},
"node_modules/isexe": {
@@ -4715,6 +6342,24 @@
"@pkgjs/parseargs": "^0.11.0"
}
},
+ "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/jest": {
"version": "30.2.0",
"resolved": "https://registry.npmjs.org/jest/-/jest-30.2.0.tgz",
@@ -5331,6 +6976,16 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
@@ -5357,6 +7012,13 @@
"node": ">=6"
}
},
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -5364,6 +7026,21 @@
"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",
@@ -5444,12 +7121,29 @@
"safe-buffer": "^5.0.1"
}
},
+ "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/kuler": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==",
"license": "MIT"
},
+ "node_modules/lazy-val": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
+ "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -5460,11 +7154,18 @@
"node": ">=6"
}
},
- "node_modules/limiter": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz",
- "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==",
- "dev": true
+ "node_modules/lilconfig": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.4.tgz",
+ "integrity": "sha512-zJZyBmQhArDRefuWTypZxwDpFDIYmrj8ypSBvwGD5P13Y95s6DjzKgu4DVdGbeQa5PDEsAOCAPNk4X+QOR006w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
},
"node_modules/lines-and-columns": {
"version": "1.2.4",
@@ -5477,7 +7178,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"p-locate": "^4.1.0"
@@ -5505,13 +7205,6 @@
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
"license": "MIT"
},
- "node_modules/lodash.isfinite": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
- "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lodash.isinteger": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
@@ -5559,6 +7252,16 @@
"node": ">= 12.0.0"
}
},
+ "node_modules/lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
@@ -5608,6 +7311,34 @@
"tmpl": "1.0.5"
}
},
+ "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/matcher/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/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -5642,6 +7373,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -5709,6 +7450,26 @@
"node": ">=6"
}
},
+ "node_modules/mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mini-svg-data-uri": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+ "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mini-svg-data-uri": "cli.js"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -5741,12 +7502,18 @@
"node": ">=16 || 14 >=14.17"
}
},
- "node_modules/mitt": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mitt/-/mitt-1.2.0.tgz",
- "integrity": "sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==",
+ "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"
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
},
"node_modules/mkdirp": {
"version": "0.5.6",
@@ -5793,6 +7560,37 @@
"node": ">= 10.16.0"
}
},
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
"node_modules/napi-postinstall": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
@@ -5835,6 +7633,55 @@
"node": ">= 0.4.0"
}
},
+ "node_modules/node-abi": {
+ "version": "4.38.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.38.0.tgz",
+ "integrity": "sha512-suSdznUPfabdaeLiNERA0LHod14RhcEn8wMPUZEQ6bKvajUCZ+aizY4pIvlLU+gImeLKp2bFDHhOc9yonISsXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": ">=22.12.0"
+ }
+ },
+ "node_modules/node-abi/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/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-api-version/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/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
@@ -5873,6 +7720,80 @@
"url": "https://opencollective.com/node-fetch"
}
},
+ "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/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/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/node-gyp/node_modules/undici": {
+ "version": "6.29.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.1.tgz",
+ "integrity": "sha512-EvRlUt/QqAEvXdQeRMYUfwOQsfzpDztykrG2owGEE/rBOBoYv9uF39ZzsNDh4lTFHhTr2XOZjKkYgueD12ZmGA==",
+ "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",
@@ -5916,6 +7837,22 @@
"url": "https://opencollective.com/nodemon"
}
},
+ "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-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -5926,6 +7863,19 @@
"node": ">=0.10.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/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -5969,6 +7919,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "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/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -6016,17 +7977,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/opn": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz",
- "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==",
+ "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",
- "dependencies": {
- "is-wsl": "^1.1.0"
- },
"engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
"node_modules/p-limit": {
@@ -6049,7 +8007,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"p-limit": "^2.2.0"
@@ -6062,7 +8019,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dev": true,
"license": "MIT",
"dependencies": {
"p-try": "^2.0.0"
@@ -6078,7 +8034,6 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -6188,7 +8143,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -6214,6 +8168,13 @@
"node": ">=8"
}
},
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
@@ -6244,6 +8205,21 @@
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
"license": "MIT"
},
+ "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/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -6258,65 +8234,312 @@
"dev": true,
"license": "ISC"
},
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkijs": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.3.tgz",
+ "integrity": "sha512-V9kOzaItwDgqlryhXysQsAXUEKi5O7kqWUaP3dXI7MLvkPqWWMb4wVb1QAtmEDCKI+XIAINsZoNKMFF7sZb1eg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "workspaces": [
+ "website"
+ ],
+ "dependencies": {
+ "@noble/hashes": "1.8.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/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/plist/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/pngjs": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
+ "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz",
+ "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.20",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+ "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+ "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "jiti": ">=1.21.0",
+ "postcss": ">=8.0.9",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
"engines": {
- "node": ">=8.6"
+ "node": ">=12.0"
},
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
+ "peerDependencies": {
+ "postcss": "^8.2.14"
}
},
- "node_modules/pirates": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
- "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.5",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.5.tgz",
+ "integrity": "sha512-TEHFzb5KRDKaOgJ4TYE+0jyJtFbjLvkdVOu0fZ2b6MTWzoqZd4Le+61aEppWkvTlYePgOX4ATL1wsAIPMLTw6Q==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
"engines": {
- "node": ">= 6"
+ "node": ">=4"
}
},
- "node_modules/pkg-dir": {
+ "node_modules/postcss-value-parser": {
"version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/posthog-node": {
+ "version": "5.56.4",
+ "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-5.56.4.tgz",
+ "integrity": "sha512-oVn/HxJZK/xen+u51nwyEpWnN4UEQox4GOSwBOp5OGli3x7Soz7Jler+CatGQsAehQuVPas2432hAarXNyxoWA==",
"license": "MIT",
"dependencies": {
- "find-up": "^4.0.0"
+ "@posthog/core": "^1.59.3"
},
"engines": {
- "node": ">=8"
+ "node": "^20.20.0 || >=22.22.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.2.0",
+ "rxjs": "^7.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ },
+ "rxjs": {
+ "optional": true
+ }
}
},
- "node_modules/portscanner": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",
- "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==",
+ "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": {
- "async": "^2.6.0",
- "is-number-like": "^1.0.3"
+ "commander": "^9.4.0"
+ },
+ "bin": {
+ "postject": "dist/cli.js"
},
"engines": {
- "node": ">=0.4",
- "npm": ">=1.0.0"
+ "node": ">=14.0.0"
}
},
- "node_modules/portscanner/node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
+ "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",
- "dependencies": {
- "lodash": "^4.17.14"
+ "optional": true,
+ "peer": true,
+ "engines": {
+ "node": "^12.20.0 || >=14"
}
},
"node_modules/pretty-format": {
@@ -6347,6 +8570,23 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "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",
@@ -6357,6 +8597,39 @@
"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/proper-lockfile/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/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -6530,6 +8803,109 @@
],
"license": "MIT"
},
+ "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.2.0",
+ "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.2.0.tgz",
+ "integrity": "sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/qrcode": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
+ "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
+ "license": "MIT",
+ "dependencies": {
+ "dijkstrajs": "^1.0.1",
+ "pngjs": "^5.0.0",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "qrcode": "bin/qrcode"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/qrcode/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "license": "ISC"
+ },
+ "node_modules/qrcode/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/qrcode/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/qs": {
"version": "6.14.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
@@ -6546,6 +8922,40 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -6577,6 +8987,44 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/read-binary-file-arch": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz",
+ "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "bin": {
+ "read-binary-file-arch": "cli.js"
+ }
+ },
+ "node_modules/read-binary-file-arch/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz",
+ "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@@ -6608,16 +9056,71 @@
"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==",
+ "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/requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "license": "ISC"
+ },
+ "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": {
+ "version": "1.22.13",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz",
+ "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.17.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
"dev": true,
"license": "MIT"
},
@@ -6654,42 +9157,128 @@
"node": ">=4"
}
},
- "node_modules/resp-modifier": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/resp-modifier/-/resp-modifier-6.0.2.tgz",
- "integrity": "sha512-U1+0kWC/+4ncRFYqQWTx/3qkfE6a4B/h3XXgmXypfa0SPZ3t7cbbaFk297PjQS/yov24R18h6OZe6iZwj3NSLw==",
+ "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": {
- "debug": "^2.2.0",
- "minimatch": "^3.0.2"
+ "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": ">= 0.8.0"
+ "node": ">= 4"
}
},
- "node_modules/resp-modifier/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "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": {
- "ms": "2.0.0"
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
}
},
- "node_modules/resp-modifier/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "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": "MIT"
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
},
- "node_modules/rx": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz",
- "integrity": "sha512-CiaiuN6gapkdl+cZUr67W6I8jquN4lkak3vtIsIWCl4XIPP8ffsoyN6/+PuGXnQy8Cu8W2y9Xxh31Rq4M6wUug==",
+ "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": "Apache-2.0"
+ "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/roarr/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/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
},
"node_modules/safe-buffer": {
"version": "5.2.1",
@@ -6726,6 +9315,16 @@
"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.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
@@ -6742,6 +9341,14 @@
"semver": "bin/semver"
}
},
+ "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/send": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
@@ -6802,90 +9409,35 @@
"node": ">=4"
}
},
- "node_modules/serve-index": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
- "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+ "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": {
- "accepts": "~1.3.4",
- "batch": "0.6.1",
- "debug": "2.6.9",
- "escape-html": "~1.0.3",
- "http-errors": "~1.6.2",
- "mime-types": "~2.1.17",
- "parseurl": "~1.3.2"
+ "type-fest": "^0.13.1"
},
"engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/serve-index/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/serve-index/node_modules/depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/serve-index/node_modules/http-errors": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
- "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.0",
- "statuses": ">= 1.4.0 < 2"
+ "node": ">=10"
},
- "engines": {
- "node": ">= 0.6"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/serve-index/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/serve-index/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/serve-index/node_modules/setprototypeof": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
- "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/serve-index/node_modules/statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "node_modules/serialize-error/node_modules/type-fest": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
+ "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
"dev": true,
- "license": "MIT",
+ "license": "(MIT OR CC0-1.0)",
+ "optional": true,
"engines": {
- "node": ">= 0.6"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/serve-static": {
@@ -6903,11 +9455,10 @@
"node": ">= 0.8.0"
}
},
- "node_modules/server-destroy": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
- "integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==",
- "dev": true,
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"license": "ISC"
},
"node_modules/setprototypeof": {
@@ -7077,138 +9628,6 @@
"npm": ">= 3.0.0"
}
},
- "node_modules/socket.io": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
- "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "accepts": "~1.3.4",
- "base64id": "~2.0.0",
- "cors": "~2.8.5",
- "debug": "~4.3.2",
- "engine.io": "~6.6.0",
- "socket.io-adapter": "~2.5.2",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.2.0"
- }
- },
- "node_modules/socket.io-adapter": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
- "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "~4.3.4",
- "ws": "~8.17.1"
- }
- },
- "node_modules/socket.io-adapter/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io-client": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
- "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.2",
- "engine.io-client": "~6.6.1",
- "socket.io-parser": "~4.2.4"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/socket.io-client/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io-parser": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
- "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@socket.io/component-emitter": "~3.1.0",
- "debug": "~4.3.1"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/socket.io-parser/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/socket.io/node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
"node_modules/socks": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
@@ -7267,6 +9686,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/source-map-js": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz",
+ "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map-support": {
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
@@ -7307,30 +9736,23 @@
"node": ">=10"
}
},
- "node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "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": ">= 0.8"
+ "node": ">= 6"
}
},
- "node_modules/stream-throttle": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz",
- "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "commander": "^2.2.0",
- "limiter": "^1.0.5"
- },
- "bin": {
- "throttleproxy": "bin/throttleproxy.js"
- },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
+ "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
"engines": {
- "node": ">= 0.10.0"
+ "node": ">= 0.8"
}
},
"node_modules/streamsearch": {
@@ -7382,7 +9804,6 @@
"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",
@@ -7413,7 +9834,6 @@
"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"
@@ -7469,6 +9889,70 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/sucrase": {
+ "version": "3.35.1",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
+ "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "tinyglobby": "^0.2.11",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/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/sumchecker/node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
"node_modules/superagent": {
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-10.3.0.tgz",
@@ -7546,6 +10030,19 @@
"node": ">=4"
}
},
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/synckit": {
"version": "0.11.12",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
@@ -7562,6 +10059,74 @@
"url": "https://opencollective.com/synckit"
}
},
+ "node_modules/tailwindcss": {
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
+ "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.7",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "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-fs": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
@@ -7589,6 +10154,57 @@
"streamx": "^2.15.0"
}
},
+ "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/temp-file/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -7642,6 +10258,107 @@
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==",
"license": "MIT"
},
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "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/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/tinyglobby/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/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
+ "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "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/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@@ -7690,6 +10407,23 @@
"node": ">= 14.0.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/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -7746,33 +10480,6 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"license": "MIT"
},
- "node_modules/ua-parser-js": {
- "version": "1.0.41",
- "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz",
- "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- }
- ],
- "license": "MIT",
- "bin": {
- "ua-parser-js": "script/cli.js"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/undefsafe": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz",
@@ -7780,10 +10487,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/undici": {
+ "version": "7.30.1",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.1.tgz",
+ "integrity": "sha512-03KrMbjIFDWQR5RNPrSw3bd1r12JpyFQl9/yxjUbJtqkjmllqC5lFjZh6ujeuJCKr8EOQvRW872Oy/az+nLYxg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
"node_modules/undici-types": {
- "version": "7.10.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
- "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"dev": true,
"license": "MIT"
},
@@ -7840,6 +10558,20 @@
"@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
}
},
+ "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/update-browserslist-db": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
@@ -7871,6 +10603,13 @@
"browserslist": ">= 4.21.0"
}
},
+ "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",
@@ -7929,6 +10668,20 @@
"node": ">= 8"
}
},
+ "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": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -7945,6 +10698,12 @@
"node": ">= 8"
}
},
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
+ "license": "ISC"
+ },
"node_modules/winston": {
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz",
@@ -8057,28 +10816,6 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
- "node_modules/ws": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
- "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
"node_modules/xml2js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
@@ -8101,15 +10838,6 @@
"node": ">=4.0"
}
},
- "node_modules/xmlhttprequest-ssl": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
- "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index 27bf724..9e4b82f 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "lanstreamer-server",
- "version": "1.2.4",
+ "version": "2.0.0",
"description": "Backend server for the LANStreamer application.",
- "main": "src/server.js",
+ "main": "electron/main.js",
"type": "module",
"scripts": {
"start": "title LANStreamer Server && node src/server.js",
@@ -10,9 +10,47 @@
"dev:simple": "nodemon src/server.js",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
+ "build:css": "tailwindcss -i src/tailwind.css -o public/assets/vendor/tailwind.css --minify",
+ "vendor:fonts": "node scripts/vendor-fonts.mjs",
+ "electron:dev": "electron electron/main.js",
+ "electron:smoke": "electron electron/main.js --smoke",
+ "electron:build:win": "node scripts/fetch-vendor-binaries.mjs && node scripts/prepare-telemetry-key.mjs && electron-builder --win nsis portable",
"setup": "node scripts/setup.js",
"screenshots": "node scripts/generate-screenshots.js"
},
+ "build": {
+ "appId": "com.lanstreamer.app",
+ "productName": "LANStreamer",
+ "files": [
+ "electron/**",
+ "src/**",
+ "public/**",
+ "package.json",
+ "README.md"
+ ],
+ "extraResources": [
+ {
+ "from": "vendor",
+ "to": "vendor"
+ }
+ ],
+ "electronLanguages": [
+ "en-US"
+ ],
+ "directories": {
+ "output": "release"
+ },
+ "win": {
+ "icon": "electron/icon.ico"
+ },
+ "portable": {
+ "artifactName": "LANStreamer Standalone ${version}.${ext}"
+ },
+ "nsis": {
+ "oneClick": true,
+ "perMachine": false
+ }
+ },
"keywords": [
"streaming",
"audio",
@@ -28,16 +66,22 @@
"jsonwebtoken": "^9.0.2",
"multer": "^2.0.2",
"node-fetch": "^3.3.2",
+ "posthog-node": "^5.56.4",
+ "qrcode": "^1.5.4",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
"xml2js": "^0.6.2"
},
"devDependencies": {
+ "@tailwindcss/container-queries": "^0.1.1",
+ "@tailwindcss/forms": "^0.5.11",
"@types/jest": "^30.0.0",
- "browser-sync": "^3.0.4",
+ "electron": "^45.0.0",
+ "electron-builder": "^26.18.0",
"jest": "^30.2.0",
"nodemon": "^2.0.0",
"puppeteer": "^24.0.0",
- "supertest": "^7.2.2"
+ "supertest": "^7.2.2",
+ "tailwindcss": "^3.4.19"
}
}
diff --git a/public/assets/css/tokens.css b/public/assets/css/tokens.css
new file mode 100644
index 0000000..690f2b2
--- /dev/null
+++ b/public/assets/css/tokens.css
@@ -0,0 +1,265 @@
+/* ============================================================================
+ LANStreamer design tokens — single source of truth for theming.
+
+ Dark (default) + light via [data-theme="light"] on .
+ Direction (Stemtracks ref, dribbble.com/shots/25182834): near-black surfaces,
+ hairline borders, ONE accent, pill buttons, uppercase micro-labels, subtle
+ glow on interactive elements. Restraint over glassmorphism.
+
+ Migration note: the "legacy var remap" + "theme shims" sections keep the
+ existing markup working under both themes while it is migrated to these
+ tokens. Delete shims as components adopt .tok-* classes.
+ ========================================================================== */
+
+:root {
+ /* Native form controls (select popups, scrollbars) follow the active theme;
+ without this Windows renders dark-styled dropdowns as black-on-black. */
+ color-scheme: dark;
+ /* Surfaces (designer palette, 2026-10-28 redesign) */
+ --tok-bg: #07090D; /* app background — near black */
+ --tok-surface-1: #0E1117; /* cards */
+ --tok-surface-2: #141821; /* raised / hover */
+ --tok-surface-inset: #0A0D12; /* wells, code, inset panels */
+
+ /* Text */
+ --tok-text-1: #EEF1F6;
+ --tok-text-2: #97A0B0;
+ --tok-text-3: #636C7C;
+
+ /* Lines + accents */
+ --tok-line: rgba(255, 255, 255, 0.07); /* hairline borders */
+ --tok-line-strong: rgba(255, 255, 255, 0.13);
+ --tok-accent: #1AA6F5; /* LANStreamer blue */
+ --tok-accent-strong: #0C86D6;
+ --tok-accent-soft: rgba(26, 166, 245, 0.13);
+ --tok-accent-contrast: #03121C; /* dark text on the bright blue */
+ --tok-accent-glow: 0 8px 24px -8px rgba(26, 166, 245, 0.5);
+
+ /* Semantic */
+ --tok-live: #2BD46A;
+ --tok-live-dim: rgba(43, 212, 106, 0.12);
+ --tok-warning: #F5A524; /* separate from danger (was danger-coloured) */
+ --tok-warning-dim: rgba(245, 165, 36, 0.13);
+ --tok-danger: #F2555A;
+ --tok-danger-dim: rgba(242, 85, 90, 0.12);
+ --tok-onair: #FF4A3B; /* reserved: the ON AIR badge only */
+
+ /* Type */
+ --tok-font: "Space Grotesk", Inter, system-ui, sans-serif;
+ --tok-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
+
+ /* Shape + depth */
+ --tok-radius-card: 14px;
+ --tok-radius-input: 10px;
+ --tok-radius-btn: 10px; /* designer moved off pill buttons */
+ --tok-shadow-card: 0 1px 0 rgba(255,255,255,0.03) inset, 0 10px 30px -14px rgba(0,0,0,0.7);
+ --tok-shadow-pop: 0 12px 40px -10px rgba(0, 0, 0, 0.65);
+
+ /* Motion */
+ --tok-ease: cubic-bezier(0.4, 0, 0.2, 1);
+ --tok-speed: 180ms;
+
+ /* Legacy var remap (existing markup reads these) */
+ --primary-color: var(--tok-accent);
+ --live-color: var(--tok-live);
+ --warning-color: var(--tok-warning);
+ --dark-bg: var(--tok-bg);
+ --card-bg: var(--tok-surface-1);
+ --border-color: var(--tok-line);
+}
+
+/* --------------------------------------------------------------------------
+ Light theme
+ -------------------------------------------------------------------------- */
+[data-theme="light"] {
+ color-scheme: light;
+ --tok-bg: #F4F5F8;
+ --tok-surface-1: #FFFFFF;
+ --tok-surface-2: #EEF0F3;
+ --tok-surface-inset: #E6E9EE;
+
+ --tok-text-1: #0E1420;
+ --tok-text-2: #5A6475;
+ --tok-text-3: #8A93A3;
+
+ --tok-line: rgba(14, 20, 32, 0.09);
+ --tok-line-strong: rgba(14, 20, 32, 0.16);
+ --tok-accent: #0A84D6;
+ --tok-accent-strong: #0868AA;
+ --tok-accent-soft: rgba(10, 132, 214, 0.10);
+ --tok-accent-contrast: #FFFFFF;
+ --tok-accent-glow: 0 8px 24px -10px rgba(10, 132, 214, 0.4);
+
+ --tok-live: #14A34D;
+ --tok-live-dim: rgba(20, 163, 77, 0.12);
+ --tok-warning: #D98A04;
+ --tok-warning-dim: rgba(217, 138, 4, 0.12);
+ --tok-danger: #D93025;
+ --tok-danger-dim: rgba(217, 48, 37, 0.10);
+ --tok-onair: #E5372B;
+
+ --tok-shadow-card: 0 1px 2px rgba(14,23,42,0.04), 0 8px 24px -12px rgba(14,23,42,0.12);
+ --tok-shadow-pop: 0 16px 44px -12px rgba(14, 23, 42, 0.25);
+}
+
+/* --------------------------------------------------------------------------
+ Button system (adopt on new + redesigned markup)
+ -------------------------------------------------------------------------- */
+.btn {
+ display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
+ min-height: 40px; /* 44px touch target with padding */
+ padding: 0 1.25rem;
+ border-radius: var(--tok-radius-btn);
+ font-size: 0.875rem; font-weight: 600; letter-spacing: 0.01em;
+ border: 1px solid transparent;
+ cursor: pointer;
+ transition: all var(--tok-speed) var(--tok-ease);
+ white-space: nowrap;
+}
+.btn:focus-visible { outline: 2px solid var(--tok-accent); outline-offset: 2px; }
+.btn:disabled { opacity: 0.5; cursor: not-allowed; }
+
+.btn-primary {
+ background: var(--tok-accent);
+ color: var(--tok-accent-contrast);
+ box-shadow: var(--tok-accent-glow);
+}
+.btn-primary:hover:not(:disabled) { filter: brightness(1.08); }
+
+.btn-secondary {
+ background: var(--tok-surface-1);
+ color: var(--tok-text-1);
+ border-color: var(--tok-line-strong);
+ box-shadow: none;
+}
+.btn-secondary:hover:not(:disabled) { background: var(--tok-surface-2); border-color: var(--tok-accent); }
+
+.btn-ghost {
+ background: transparent;
+ color: var(--tok-text-2);
+}
+.btn-ghost:hover:not(:disabled) { color: var(--tok-text-1); background: var(--tok-surface-2); }
+
+.btn-danger {
+ background: transparent;
+ color: var(--tok-danger);
+ border-color: color-mix(in oklab, var(--tok-danger) 35%, transparent);
+}
+.btn-danger:hover:not(:disabled) { background: var(--tok-danger-dim); }
+
+/* Micro label — mono, uppercase, tracked (eyebrow) */
+.tok-label {
+ font-family: var(--tok-mono);
+ font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.08em;
+ text-transform: uppercase; color: var(--tok-text-3);
+}
+.mono { font-family: var(--tok-mono); font-size: 0.75rem; letter-spacing: 0.01em; }
+
+/* --------------------------------------------------------------------------
+ Theme shims — make existing dark-hardcoded markup usable in light mode.
+ REMOVE each line as the component adopts tokens.
+ -------------------------------------------------------------------------- */
+[data-theme="light"] .text-white { color: var(--tok-text-1); }
+[data-theme="light"] .text-gray-300 { color: var(--tok-text-2); }
+[data-theme="light"] .text-gray-400 { color: var(--tok-text-2); }
+[data-theme="light"] .text-gray-500 { color: var(--tok-text-3); }
+[data-theme="light"] .bg-black\/50,
+[data-theme="light"] .bg-black\/60 { background-color: rgba(15, 23, 42, 0.45); }
+[data-theme="light"] .bg-gray-700 { background-color: var(--tok-line-strong); }
+[data-theme="light"] .border-gray-600 { border-color: var(--tok-line-strong); }
+
+/* Page background per theme (html prefix wins the specificity tie against
+ the pages' inline
+
+
+
+
+
+
+
+
Troubleshooting & Guide
+
Everything in one page — works offline
+
+
+
+
+ light_mode
+
+
+
+
+
+ Admin access
+ Streams
+ Audio sources
+ Network & phones
+ Latency
+ Minimum specs
+
+
+
+ lock Admin access
+ The admin dashboard is protected by a login. The listener page has no login —
+ phones on the network just open the shared /streams link.
+
+ Sign in at http://localhost:3001/dashboard (or in the Electron app window) with your
+ admin username and password — the defaults ship in the project README.md under
+ “Admin access”, and can be changed with the ADMIN_USERNAME / ADMIN_PASSWORD
+ environment variables. On first run the dashboard shows a banner stating the defaults and how to
+ change them; it disappears once you set your own.
+ Change it in the app: dashboard → sidebar → Admin account card — new
+ username + password, applies immediately (works in the desktop app, where there is no .env).
+ Forgot your password? On this PC, delete the admin login file and restart
+ LANStreamer — the documented default login returns, and you can set a new one from the Admin account
+ card. Installed app: %APPDATA%\LANStreamer\security.json · from source:
+ config\security.json. (The login page shows this hint too.)
+ Admin is also locked to localhost : other machines on the network only ever see
+ the listener page, even with valid credentials.
+ The bundled Icecast is hardened for you: it only listens on this PC
+ (127.0.0.1) and its passwords are randomly generated per install — listeners get audio
+ through LANStreamer's port 3001, never Icecast directly. Using your own Icecast install? Change its
+ stock passwords; the dashboard warns until you do.
+ Never port-forward ports 3001/8200 to the internet — the localhost lock only protects you on your LAN.
+ Remote admin over the internet: use a VPN like Tailscale instead of exposing ports.
+
+
+
+
+ podcasts Streams
+
+ Start with the app (auto-start)
+ Streams saved with Start with app enabled come up automatically when LANStreamer
+ launches — including the Icecast server, which starts itself if it isn't running yet. Stop a stream and
+ disable the toggle if you want it to stay down across restarts.
+
+ “Audio source busy — already used by …”
+ One audio input can feed one running stream at a time. Windows audio capture is exclusive
+ per process, so a second stream on the same source cannot start.
+
+ Stop the other stream named in the message, or
+ Edit this stream and pick a different audio source, then Start.
+
+
+ “Audio source … could not be opened”
+ FFmpeg could see the device name but not open it as a capture device.
+
+ If the source is a virtual camera's audio pin (e.g. OBS Virtual Camera ), it cannot be captured — use OBS's actual audio output via a virtual cable (VoiceMeeter / VB-Cable) instead.
+ Close other apps holding the mic (Zoom, Teams, Discord, Audacity, OBS itself).
+ Restart VoiceMeeter / VB-Cable if you use virtual devices, then Refresh Devices.
+
+
+ “Cannot connect to Icecast”
+
+ Check the Icecast panel on the dashboard — it should say Online . Start it if not (LANStreamer also auto-starts it when you go live).
+ Port conflict: run netstat -ano | findstr ":8200" — if another app (e.g. Docker) holds the port, stop it or change the port in icecast.xml.
+ Restart Icecast from its panel (Stop → Start).
+ Windows Firewall: allow icecast.exe on private networks.
+
+
+ The app opened on port 3002, or “port 3001 already in use”
+ Another LANStreamer server instance is still running — usually a leftover node server
+ from a terminal (the window with the “DO NOT CLOSE THIS TERMINAL” message), or a second copy
+ of the app. Two instances share the same stream settings and fight over audio devices, so stop one:
+
+ On the dashboard of the instance you're keeping, stop every stream and the Icecast
+ server — that frees the audio devices cleanly (the stop buttons end the encoders properly).
+ Note: there is deliberately no “stop server” button — a web server cannot stop itself over HTTP.
+ To end the server process itself, close its terminal window (or quit the Electron app from the tray),
+ or kill it from Task Manager (node.exe listening on port 3001).
+ Relaunch the app — it takes port 3001 back and starts clean.
+
+
+ Stream stuck on “starting” / listener can't hear anything
+ The stream row status refreshes every 5 seconds. If a stream shows an error or stopped:
+
+ Open the error's Details on the row — the top line says what failed.
+ If the machine's IP changed (DHCP), restart LANStreamer; it re-syncs Icecast's hostname automatically.
+ Ask listeners to tap play again — the listener page auto-resumes a stream that comes back on air.
+
+
+
+
+ mic Audio sources
+ Devices listed twice
+ Fixed in current versions — duplicate entries are de-duplicated. If you still see doubles after plugging a
+ new device in, click Refresh Devices (icon in the sources card).
+ Routing app audio into LANStreamer
+ Windows only exposes microphones as capture devices. To stream what a player/DJ app plays, install a virtual
+ cable and pick it as the stream source:
+
+ VoiceMeeter (donationware) — mixer + virtual outputs.
+ VB-Audio Virtual Cable — simple in/out pair.
+
+
+ info
+ Pick the cable output (what apps play into) as LANStreamer's input source, and set the same
+ cable as the default playback device in your music app.
+
+
+
+
+ wifi Network & phones
+ Listener address
+ Listeners open http://<your-ip>:3001/streams — use the QR code / copy button in
+ the dashboard header to share the exact address.
+ The IP changed (DHCP)
+ LANStreamer detects IP changes and re-syncs, but bookmarks on phones still point at the old IP. Best fix:
+ give the streaming PC a static DHCP reservation in your router, then have listeners re-open
+ the shared link once. Listeners can also bookmark /streams in their browser.
+ Page is blank
+ A blank page means the server isn't reachable (wrong IP, server off, or different Wi-Fi). The listener page
+ itself shows “No live streams” whenever the server is up but nothing is on air.
+
+
+
+ speed Latency
+ Total delay from mic to ears is typically 2–6 seconds . Fastest wins:
+
+ Operator side: 5 GHz Wi-Fi or wired for the streaming PC; keep it away from congestion; QoS/streaming priority on the router helps on busy networks.
+ Listener side: phones on the same AP/SSID; close background streaming apps; wired headsets avoid Bluetooth's extra 100–200 ms.
+ In LANStreamer: lower bitrate (128 kbps) trims buffer a little; keep the listener volume above ~50% and use the on-page volume.
+
+ Full write-up: docs/LATENCY.md in the repository.
+
+
+
+ memory Minimum specs
+
+ Windows 10/11 (64-bit), 4 GB RAM, dual-core CPU
+ FFmpeg and Icecast 2.4+ (bundled with the installer)
+ Wired or solid Wi-Fi to the same network as the listeners
+ Listeners: any modern phone browser (Chrome/Safari/Edge, ~2019+)
+
+
+
+
+
+
+