diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..0a585dc --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,64 @@ +#!/bin/bash +set -euo pipefail + +CONFIG=".canpixel-ci.json" +RUN_TSC=true +RUN_LINT=true +RUN_PRETTIER=true + +if [ -f "$CONFIG" ]; then + RUN_TSC=$(jq -r '.run_tsc // true' "$CONFIG") + RUN_LINT=$(jq -r '.run_lint // true' "$CONFIG") + RUN_PRETTIER=$(jq -r '.run_prettier // true' "$CONFIG") +fi + +if [ -f bun.lockb ] || [ -f bun.lock ]; then PM="bun" +elif [ -f pnpm-lock.yaml ]; then PM="pnpm" +elif [ -f yarn.lock ]; then PM="yarn" +else PM="npm"; fi + +FAILED=() + +if [ "$RUN_TSC" = "true" ]; then + echo "→ tsc..." >&2 + case "$PM" in + bun) bun run typecheck 2>&1 || FAILED+=("tsc") ;; + pnpm) pnpm run typecheck 2>&1 || FAILED+=("tsc") ;; + yarn) yarn typecheck 2>&1 || FAILED+=("tsc") ;; + npm) npm run typecheck 2>&1 || FAILED+=("tsc") ;; + esac +fi + +if [ "$RUN_LINT" = "true" ]; then + echo "→ lint..." >&2 + case "$PM" in + bun) bun run lint 2>&1 || FAILED+=("lint") ;; + pnpm) pnpm run lint 2>&1 || FAILED+=("lint") ;; + yarn) yarn lint 2>&1 || FAILED+=("lint") ;; + npm) npm run lint 2>&1 || FAILED+=("lint") ;; + esac +fi + +if [ "$RUN_PRETTIER" = "true" ]; then + echo "→ prettier..." >&2 + case "$PM" in + bun) bunx prettier --check . 2>&1 || FAILED+=("prettier") ;; + pnpm) pnpm exec prettier --check . 2>&1 || FAILED+=("prettier") ;; + yarn) yarn format:check 2>&1 || FAILED+=("prettier") ;; + npm) npx prettier --check . 2>&1 || FAILED+=("prettier") ;; + esac +fi + +if [ ${#FAILED[@]} -gt 0 ]; then + echo "" >&2 + echo "╔══════════════════════════════════════╗" >&2 + echo "║ ✗ Commit blocked by CanPixel CI ║" >&2 + echo "╠══════════════════════════════════════╣" >&2 + for check in "${FAILED[@]}"; do + printf "║ • %-34s║\n" "$check failed" >&2 + done + echo "╚══════════════════════════════════════╝" >&2 + exit 1 +fi + +echo "✓ all checks passed" >&2 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 788807f..a171526 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,7 +38,11 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm - uses: dtolnay/rust-toolchain@stable with: targets: aarch64-apple-darwin,x86_64-apple-darwin @@ -46,20 +50,20 @@ jobs: with: workspaces: src-tauri - - run: bun install --frozen-lockfile + - run: pnpm install --frozen-lockfile - id: updater uses: ./.github/actions/updater-flags # Keep this in step with `build:macos-universal`. The updater config must be # inserted into the Tauri invocation, so CI spells the command out here. - - run: bun run typecheck - - run: bun run tauri build --bundles app --target universal-apple-darwin ${{ steps.updater.outputs.config }} + - run: pnpm run typecheck + - run: pnpm run tauri build --bundles app --target universal-apple-darwin ${{ steps.updater.outputs.config }} - name: Verify universal app binary run: | lipo "src-tauri/target/universal-apple-darwin/release/bundle/macos/ÆTHER.app/Contents/MacOS/aether" \ -verify_arch arm64 x86_64 - - run: AETHER_TAURI_TARGET=universal-apple-darwin bun run dmg + - run: AETHER_TAURI_TARGET=universal-apple-darwin pnpm run dmg - uses: actions/upload-artifact@v4 with: @@ -94,21 +98,27 @@ jobs: libssl-dev libgtk-3-dev libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev librsvg2-dev - - uses: oven-sh/setup-bun@v2 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm - uses: dtolnay/rust-toolchain@stable - uses: swatinem/rust-cache@v2 with: workspaces: src-tauri - - run: bun install --frozen-lockfile - - run: bun run typecheck:web + # appdmg is macOS-only, but pnpm still sees its native helper in the + # locked dependency graph. Do not run dependency build scripts here. + - run: pnpm install --frozen-lockfile --ignore-scripts + - run: pnpm run typecheck:web # Unit tests are platform-independent, so one runner is enough. - - run: bun run test + - run: pnpm run test - id: updater uses: ./.github/actions/updater-flags - - run: bun run tauri build --bundles deb,appimage ${{ steps.updater.outputs.config }} + - run: pnpm run tauri build --bundles deb,appimage ${{ steps.updater.outputs.config }} - run: scripts/normalize-deb-package.sh src-tauri/target/release/bundle/deb/*.deb - uses: actions/upload-artifact@v4 @@ -145,15 +155,21 @@ jobs: libssl-dev libgtk-3-dev libwebkit2gtk-4.1-dev \ libayatana-appindicator3-dev librsvg2-dev - - uses: oven-sh/setup-bun@v2 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm - uses: dtolnay/rust-toolchain@stable - uses: swatinem/rust-cache@v2 with: workspaces: src-tauri - - run: bun install --frozen-lockfile - - run: bun run typecheck:web - - run: bun run tauri build --bundles deb + # appdmg is macOS-only, but pnpm still sees its native helper in the + # locked dependency graph. Do not run dependency build scripts here. + - run: pnpm install --frozen-lockfile --ignore-scripts + - run: pnpm run typecheck:web + - run: pnpm run tauri build --bundles deb - run: scripts/normalize-deb-package.sh src-tauri/target/release/bundle/deb/*.deb - uses: actions/upload-artifact@v4 @@ -172,19 +188,25 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm - uses: dtolnay/rust-toolchain@stable - uses: swatinem/rust-cache@v2 with: workspaces: src-tauri - - run: bun install --frozen-lockfile - - run: bun run typecheck:web + # appdmg is macOS-only, but pnpm still sees its native helper in the + # locked dependency graph. Do not run dependency build scripts here. + - run: pnpm install --frozen-lockfile --ignore-scripts + - run: pnpm run typecheck:web - id: updater uses: ./.github/actions/updater-flags - - run: bun run tauri build --bundles nsis ${{ steps.updater.outputs.config }} + - run: pnpm run tauri build --bundles nsis ${{ steps.updater.outputs.config }} - uses: actions/upload-artifact@v4 with: @@ -215,7 +237,11 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm - uses: actions/setup-java@v4 with: distribution: temurin @@ -237,8 +263,10 @@ jobs: echo "NDK_HOME=$ANDROID_SDK_ROOT/ndk/$NDK_VERSION" >> "$GITHUB_ENV" echo "ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/$NDK_VERSION" >> "$GITHUB_ENV" - - run: bun install --frozen-lockfile - - run: bun run tauri android build --apk --target aarch64 + # appdmg is macOS-only, but pnpm still sees its native helper in the + # locked dependency graph. Do not run dependency build scripts here. + - run: pnpm install --frozen-lockfile --ignore-scripts + - run: pnpm run tauri android build --apk --target aarch64 - uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 0fe1b59..ef4e820 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -32,10 +32,19 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - - run: bun install --frozen-lockfile - - run: bun run lint - - run: bun run typecheck:web + # action-setup must precede setup-node: the pnpm cache key setup-node + # computes needs the pnpm binary to already be on PATH. It reads the + # version from the "packageManager" field in package.json. + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v4 + with: + node-version: 24 + cache: pnpm + # appdmg is macOS-only, but pnpm still sees its native helper in the + # locked dependency graph. Do not run dependency build scripts here. + - run: pnpm install --frozen-lockfile --ignore-scripts + - run: pnpm run lint + - run: pnpm run typecheck:web rust: name: ${{ matrix.name }} diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml new file mode 100644 index 0000000..d64185f --- /dev/null +++ b/.github/workflows/quality.yml @@ -0,0 +1,30 @@ +name: Quality + +on: + pull_request: + paths-ignore: + - '**/*.md' + push: + branches: + - $default-branch + paths-ignore: + - '**/*.md' + workflow_dispatch: + +permissions: + contents: write + pull-requests: read + +jobs: + ts-checks: + uses: CanPixel/.github/.github/workflows/typescript-checks.yml@main + secrets: inherit + with: + package-manager: auto + node-version: '22' + run-lint: true + # The reusable workflow runs on bare Ubuntu and cannot install Tauri's + # GTK/WebKit system libraries. checks.yml typechecks the renderer and + # compiles Rust on all desktop platforms with the required native SDKs. + run-tsc: false + run-prettier: true diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..819595c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "printWidth": 100, + "trailingComma": "all" +} diff --git a/.prettierrc.yaml b/.prettierrc.yaml deleted file mode 100644 index 35893b3..0000000 --- a/.prettierrc.yaml +++ /dev/null @@ -1,4 +0,0 @@ -singleQuote: true -semi: false -printWidth: 100 -trailingComma: none diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 861c2fc..ad49ec5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,10 +51,10 @@ Setup and prerequisites are in the [README](README.md#development-prerequisites) Before opening a pull request: ```bash -bun run typecheck # tsc + cargo check -bun run lint # eslint -bun run test # cargo test --lib -bun run format # prettier +pnpm run typecheck # tsc + cargo check +pnpm run lint # eslint +pnpm run test # cargo test --lib +pnpm run format # prettier ``` Rust also needs to be clippy-clean: diff --git a/README.md b/README.md index a175369..fa82d7f 100644 --- a/README.md +++ b/README.md @@ -543,7 +543,7 @@ Renderer responsibilities: ## Tests ```bash -bun run test +pnpm run test ``` Runs the Rust unit suite (also run in CI on the Linux job). Alongside the usual unit @@ -568,7 +568,10 @@ AETHER_EMBEDDING_MODEL=/path/to/embedding.gguf cargo test --manifest-path src-ta Required: -- Bun for dependency management and scripts. +- Node.js 24 or newer. The release scripts and the test suite are TypeScript run + directly by Node, which needs the native type stripping added in 22.6. +- pnpm for dependency management and scripts. The version is pinned in the + `packageManager` field of `package.json`; `corepack enable pnpm` will match it. - Rust and the Tauri platform prerequisites for your target OS. - CMake, required for building the bundled llama.cpp Rust binding. - macOS, Windows, or Linux for desktop development. @@ -579,27 +582,27 @@ Required: Install dependencies: ```bash -bun install +pnpm install ``` Run the app in development: ```bash -bun run dev +pnpm run dev ``` Run checks: ```bash -bun run typecheck -bun run lint -bun run build:vite +pnpm run typecheck +pnpm run lint +pnpm run build:vite ``` Build compiled app bundles: ```bash -bun run build +pnpm run build ``` ## Android Build @@ -614,7 +617,7 @@ Install Android Studio, then install these SDK pieces through Android Studio's S - Android NDK - Android Emulator, if you want emulator testing -The `bun run android:*` scripts go through `scripts/android.sh`, which resolves `ANDROID_HOME`, picks the newest installed NDK, and exports the NDK variable spellings the whole toolchain needs (llama.cpp's build script reads `ANDROID_NDK_ROOT`, which the Tauri CLI does not set). If your SDK lives somewhere other than `~/Library/Android/sdk`, set the variables in your shell profile: +The `pnpm run android:*` scripts go through `scripts/android.sh`, which resolves `ANDROID_HOME`, picks the newest installed NDK, and exports the NDK variable spellings the whole toolchain needs (llama.cpp's build script reads `ANDROID_NDK_ROOT`, which the Tauri CLI does not set). If your SDK lives somewhere other than `~/Library/Android/sdk`, set the variables in your shell profile: ```bash export ANDROID_HOME="$HOME/Library/Android/sdk" @@ -638,13 +641,13 @@ yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses Initialize the Android project once: ```bash -bun run android:init +pnpm run android:init ``` Run on a connected device or emulator: ```bash -bun run android:dev +pnpm run android:dev ``` If this reports `No available Android Emulator detected`, start an emulator from Android Studio's Device Manager or connect a physical device with USB debugging enabled, then confirm it is visible: @@ -656,19 +659,19 @@ adb devices Build Android release artifacts: ```bash -bun run android:build +pnpm run android:build ``` Build an APK: ```bash -bun run android:build:apk +pnpm run android:build:apk ``` Build an AAB for Play Store distribution: ```bash -bun run android:build:aab +pnpm run android:build:aab ``` Android outputs are generated under: @@ -684,17 +687,17 @@ Android browser behavior: Tauri's per-tab child webviews (`Window::add_child`) a Use the Docker-based Linux build script (`scripts/build-linux.sh`) to build a Linux package from macOS or another non-Linux host. Arch is parametrized, defaulting to arm64: ```bash -bun run linux:arm64:build # aarch64 .deb -bun run linux:x64:build # x86_64 .deb +pnpm run linux:arm64:build # aarch64 .deb +pnpm run linux:x64:build # x86_64 .deb ``` -This runs an `ubuntu:24.04` container, installs the Linux Tauri + llama.cpp build dependencies (including `cmake`/`clang`), installs Bun and Rust inside Docker volumes, and builds a `.deb`. +This runs an `ubuntu:24.04` container, installs the Linux Tauri + llama.cpp build dependencies (including `cmake`/`clang`), installs Node, pnpm, and Rust inside Docker volumes, and builds a `.deb`. The default export is a Debian package for Ubuntu: ```bash -bun run linux:arm64:deb -bun run linux:x64:deb +pnpm run linux:arm64:deb +pnpm run linux:x64:deb ``` Artifacts are generated under (slug is `arm64` or `x64`): @@ -703,16 +706,16 @@ Artifacts are generated under (slug is `arm64` or `x64`): src-tauri/target-linux-//release/bundle/ ``` -The script keeps Linux-specific dependencies out of the host project by mounting per-arch Docker volumes for `/work/node_modules`, `/root/.cargo`, `/root/.rustup`, and `/root/.bun`. +The script keeps Linux-specific dependencies out of the host project by mounting per-arch Docker volumes for `/work/node_modules`, `/root/.cargo`, `/root/.rustup`, and `/root/.local/share/pnpm`. Note: building x86_64 on an arm64 Mac (or vice-versa) runs under QEMU emulation, which is very slow for the llama.cpp C++ compile. For the non-native arch, prefer CI (see below). Optional overrides: ```bash -LINUX_IMAGE=ubuntu:24.04 bun run linux:arm64:build -LINUX_BUNDLES=deb,appimage bun run linux:arm64:build -LINUX_DOCKER_PLATFORM=linux/amd64 LINUX_TARGET=x86_64-unknown-linux-gnu LINUX_ARCH_SLUG=x64 bun run linux:arm64:build +LINUX_IMAGE=ubuntu:24.04 pnpm run linux:arm64:build +LINUX_BUNDLES=deb,appimage pnpm run linux:arm64:build +LINUX_DOCKER_PLATFORM=linux/amd64 LINUX_TARGET=x86_64-unknown-linux-gnu LINUX_ARCH_SLUG=x64 pnpm run linux:arm64:build ``` ## macOS, Windows, and Linux via CI @@ -740,8 +743,8 @@ GitHub also adds source archives automatically. On a manual `workflow_dispatch` Keep release versions synced from `package.json`: ```bash -bun run version:bump 1.0.1 -bun run version:check +pnpm run version:bump 1.0.1 +pnpm run version:check git add package.json src-tauri/Cargo.toml src-tauri/Cargo.lock src-tauri/tauri.conf.json git commit -m "chore: release v1.0.1" git tag v1.0.1 @@ -752,34 +755,34 @@ git push origin v1.0.1 Build the current desktop app with Tauri: ```bash -bun run build +pnpm run build ``` ## Project Scripts -| Script | Purpose | -| ------------------------------- | ------------------------------------------------------------------------------------------------ | -| `bun run dev` | Start the Tauri desktop app in development. | -| `bun run start` | Alias for the Tauri desktop development app. | -| `bun run dev:vite` | Start only the Vite renderer dev server on `127.0.0.1:1420`. | -| `bun run format` | Format the project with Prettier. | -| `bun run typecheck:web` | Run renderer TypeScript checks. | -| `bun run typecheck:tauri` | Run Rust `cargo check` for the Tauri backend. | -| `bun run typecheck` | Run renderer TypeScript checks and Rust `cargo check` for the Tauri backend. | -| `bun run version:bump 1.2.3` | Sync `package.json`, `src-tauri/Cargo.toml`, and `src-tauri/tauri.conf.json` to one app version. | -| `bun run version:check` | Verify the app version manifests match `package.json`. | -| `bun run lint` | Run ESLint. | -| `bun run build:vite` | Build only the Vite renderer assets into `dist/`. | -| `bun run build` | Typecheck and build the Tauri desktop app. | -| `bun run build:macos-universal` | Typecheck and build the universal Apple Silicon + Intel macOS app and DMG. | -| `bun run build:desktop-local` | Build local desktop packages for the current Tauri target plus Docker Linux arm64/x64 packages. | -| `bun run android:dev` | Run the Tauri Android app on a connected device or emulator. | -| `bun run android:build:apk` | Build an Android APK. | -| `bun run android:build:aab` | Build an Android App Bundle. | -| `bun run linux:arm64:build` | Build an Ubuntu arm64 Tauri package in Docker. | -| `bun run linux:x64:build` | Build an Ubuntu x86_64 Tauri package in Docker. | -| `bun run linux:arm64:deb` | Build an Ubuntu arm64 `.deb` package in Docker. | -| `bun run linux:x64:deb` | Build an Ubuntu x86_64 `.deb` package in Docker. | +| Script | Purpose | +| -------------------------------- | ------------------------------------------------------------------------------------------------ | +| `pnpm run dev` | Start the Tauri desktop app in development. | +| `pnpm run start` | Alias for the Tauri desktop development app. | +| `pnpm run dev:vite` | Start only the Vite renderer dev server on `127.0.0.1:1420`. | +| `pnpm run format` | Format the project with Prettier. | +| `pnpm run typecheck:web` | Run renderer TypeScript checks. | +| `pnpm run typecheck:tauri` | Run Rust `cargo check` for the Tauri backend. | +| `pnpm run typecheck` | Run renderer TypeScript checks and Rust `cargo check` for the Tauri backend. | +| `pnpm run version:bump 1.2.3` | Sync `package.json`, `src-tauri/Cargo.toml`, and `src-tauri/tauri.conf.json` to one app version. | +| `pnpm run version:check` | Verify the app version manifests match `package.json`. | +| `pnpm run lint` | Run ESLint. | +| `pnpm run build:vite` | Build only the Vite renderer assets into `dist/`. | +| `pnpm run build` | Typecheck and build the Tauri desktop app. | +| `pnpm run build:macos-universal` | Typecheck and build the universal Apple Silicon + Intel macOS app and DMG. | +| `pnpm run build:desktop-local` | Build local desktop packages for the current Tauri target plus Docker Linux arm64/x64 packages. | +| `pnpm run android:dev` | Run the Tauri Android app on a connected device or emulator. | +| `pnpm run android:build:apk` | Build an Android APK. | +| `pnpm run android:build:aab` | Build an Android App Bundle. | +| `pnpm run linux:arm64:build` | Build an Ubuntu arm64 Tauri package in Docker. | +| `pnpm run linux:x64:build` | Build an Ubuntu x86_64 Tauri package in Docker. | +| `pnpm run linux:arm64:deb` | Build an Ubuntu arm64 `.deb` package in Docker. | +| `pnpm run linux:x64:deb` | Build an Ubuntu x86_64 `.deb` package in Docker. | ## Build Outputs @@ -805,10 +808,10 @@ src-tauri/gen/android/app/build/outputs/ For quick local desktop testing, prefer: ```bash -bun run dev +pnpm run dev ``` -Use `bun run build` when you need packaged Tauri desktop artifacts. +Use `pnpm run build` when you need packaged Tauri desktop artifacts. ## Desktop Packaging Notes @@ -823,7 +826,7 @@ Local desktop builds are suitable for development on your own machine. For exter If a packaged app behaves differently from development, rebuild from a clean package state: ```bash -bun run build +pnpm run build ``` ## Troubleshooting @@ -858,8 +861,8 @@ The desktop app allows browser popups through Tauri child webview handling and r Move the missing runtime package into `dependencies`, reinstall, and rebuild: ```bash -bun install -bun run build +pnpm install +pnpm run build ``` ### Packaged app has missing dashboard images or renderer assets @@ -871,8 +874,8 @@ Use Vite-compatible asset imports or renderer-public assets. Avoid assuming `/so Recheck and rebuild the Tauri backend: ```bash -bun run typecheck:tauri -bun run build +pnpm run typecheck:tauri +pnpm run build ``` ### macOS packaged app has stale bundle behavior @@ -880,7 +883,7 @@ bun run build Stale package output can preserve old assets or bundle metadata. Rebuild from a fresh package state: ```bash -bun run build +pnpm run build ``` If needed, delete stale `dist/` and `src-tauri/target/release/bundle/` output manually before rebuilding. diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index 7e04542..d80886a 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -59,7 +59,7 @@ cargo install cargo-bundle-licenses cargo bundle-licenses --format yaml --output ../THIRD_PARTY_RUST.yaml # JavaScript dependencies -bunx license-checker-rseidelsohn --production --markdown +pnpm dlx license-checker-rseidelsohn --production --markdown ``` --- diff --git a/bun.lock b/bun.lock deleted file mode 100644 index 430a666..0000000 --- a/bun.lock +++ /dev/null @@ -1,551 +0,0 @@ -{ - "lockfileVersion": 1, - "configVersion": 0, - "workspaces": { - "": { - "name": "aether-browser", - "dependencies": { - "ldrs": "^1.1.9", - "lucide-react": "^1.26.0", - }, - "devDependencies": { - "@babel/core": "^8.0.1", - "@eslint/js": "^9.39.5", - "@tauri-apps/api": "^2.11.1", - "@tauri-apps/cli": "^2.11.4", - "@types/bun": "^1.3.14", - "@types/node": "^25.9.5", - "@types/react": "^19.2.17", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.4", - "appdmg": "^0.6.6", - "brace-expansion": "^5.0.8", - "eslint": "^10.8.0", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-react-hooks": "^7.1.1", - "eslint-plugin-react-refresh": "^0.5.3", - "prettier": "^3.9.6", - "react": "^19.2.8", - "react-dom": "^19.2.8", - "typescript": "^6.0.3", - "typescript-eslint": "^8.65.0", - "vite": "^8.1.5", - }, - }, - }, - "overrides": { - "@babel/core": "^7.29.1", - "brace-expansion": "^5.0.7", - }, - "packages": { - "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], - - "@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="], - - "@babel/core": ["@babel/core@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="], - - "@babel/generator": ["@babel/generator@7.29.7", "", { "dependencies": { "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="], - - "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], - - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="], - - "@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="], - - "@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="], - - "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="], - - "@babel/traverse": ["@babel/traverse@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/types": "^7.29.7", "debug": "^4.3.1" } }, "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw=="], - - "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], - - "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], - - "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], - - "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], - - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], - - "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], - - "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], - - "@eslint/config-helpers": ["@eslint/config-helpers@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw=="], - - "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], - - "@eslint/js": ["@eslint/js@9.39.5", "", {}, "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A=="], - - "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], - - "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.2", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A=="], - - "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="], - - "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="], - - "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="], - - "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], - - "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], - - "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], - - "@oxc-project/types": ["@oxc-project/types@0.139.0", "", {}, "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw=="], - - "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.5", "", { "os": "android", "cpu": "arm64" }, "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ=="], - - "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw=="], - - "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.1.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g=="], - - "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.1.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA=="], - - "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.1.5", "", { "os": "linux", "cpu": "arm" }, "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw=="], - - "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.1.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q=="], - - "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.1.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA=="], - - "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.1.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg=="], - - "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.1.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA=="], - - "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ=="], - - "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg=="], - - "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.1.5", "", { "os": "none", "cpu": "arm64" }, "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw=="], - - "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.1.5", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA=="], - - "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.1.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw=="], - - "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA=="], - - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="], - - "@tauri-apps/api": ["@tauri-apps/api@2.11.1", "", {}, "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA=="], - - "@tauri-apps/cli": ["@tauri-apps/cli@2.11.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.4", "@tauri-apps/cli-darwin-x64": "2.11.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", "@tauri-apps/cli-linux-arm64-musl": "2.11.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-musl": "2.11.4", "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", "@tauri-apps/cli-win32-x64-msvc": "2.11.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ=="], - - "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.11.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ=="], - - "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.11.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A=="], - - "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.11.4", "", { "os": "linux", "cpu": "arm" }, "sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ=="], - - "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA=="], - - "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.11.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw=="], - - "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.11.4", "", { "os": "linux", "cpu": "none" }, "sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ=="], - - "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ=="], - - "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.11.4", "", { "os": "linux", "cpu": "x64" }, "sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A=="], - - "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.11.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ=="], - - "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.11.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA=="], - - "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.11.4", "", { "os": "win32", "cpu": "x64" }, "sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw=="], - - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], - - "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], - - "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], - - "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], - - "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - - "@types/node": ["@types/node@25.9.5", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg=="], - - "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], - - "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], - - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.65.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.65.0", "@typescript-eslint/type-utils": "8.65.0", "@typescript-eslint/utils": "8.65.0", "@typescript-eslint/visitor-keys": "8.65.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.65.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA=="], - - "@typescript-eslint/parser": ["@typescript-eslint/parser@8.65.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.65.0", "@typescript-eslint/types": "8.65.0", "@typescript-eslint/typescript-estree": "8.65.0", "@typescript-eslint/visitor-keys": "8.65.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA=="], - - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.65.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.65.0", "@typescript-eslint/types": "^8.65.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q=="], - - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.65.0", "", { "dependencies": { "@typescript-eslint/types": "8.65.0", "@typescript-eslint/visitor-keys": "8.65.0" } }, "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg=="], - - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.65.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg=="], - - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.65.0", "", { "dependencies": { "@typescript-eslint/types": "8.65.0", "@typescript-eslint/typescript-estree": "8.65.0", "@typescript-eslint/utils": "8.65.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g=="], - - "@typescript-eslint/types": ["@typescript-eslint/types@8.65.0", "", {}, "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg=="], - - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.65.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.65.0", "@typescript-eslint/tsconfig-utils": "8.65.0", "@typescript-eslint/types": "8.65.0", "@typescript-eslint/visitor-keys": "8.65.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg=="], - - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.65.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.65.0", "@typescript-eslint/types": "8.65.0", "@typescript-eslint/typescript-estree": "8.65.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA=="], - - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.65.0", "", { "dependencies": { "@typescript-eslint/types": "8.65.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A=="], - - "@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.4", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg=="], - - "acorn": ["acorn@8.16.0", "", { "bin": "bin/acorn" }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], - - "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], - - "appdmg": ["appdmg@0.6.6", "", { "dependencies": { "async": "^1.4.2", "ds-store": "^0.1.5", "execa": "^1.0.0", "fs-temp": "^1.0.0", "fs-xattr": "^0.3.0", "image-size": "^0.7.4", "is-my-json-valid": "^2.20.0", "minimist": "^1.1.3", "parse-color": "^1.0.0", "path-exists": "^4.0.0", "repeat-string": "^1.5.4" }, "os": "darwin", "bin": { "appdmg": "bin/appdmg.js" } }, "sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg=="], - - "async": ["async@1.5.2", "", {}, "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w=="], - - "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - - "base32-encode": ["base32-encode@1.2.0", "", { "dependencies": { "to-data-view": "^1.1.0" } }, "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A=="], - - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.29", "", { "bin": "dist/cli.cjs" }, "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ=="], - - "bplist-creator": ["bplist-creator@0.0.8", "", { "dependencies": { "stream-buffers": "~2.2.0" } }, "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA=="], - - "brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="], - - "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": "cli.js" }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], - - "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], - - "caniuse-lite": ["caniuse-lite@1.0.30001792", "", {}, "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw=="], - - "color-convert": ["color-convert@0.5.3", "", {}, "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling=="], - - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - - "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], - - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - - "ds-store": ["ds-store@0.1.6", "", { "dependencies": { "bplist-creator": "~0.0.3", "macos-alias": "~0.2.5", "tn1150": "^0.1.0" } }, "sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw=="], - - "electron-to-chromium": ["electron-to-chromium@1.5.353", "", {}, "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w=="], - - "encode-utf8": ["encode-utf8@1.0.3", "", {}, "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="], - - "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - - "eslint": ["eslint@10.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ=="], - - "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": "bin/cli.js" }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], - - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="], - - "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.5.3", "", { "peerDependencies": { "eslint": "^9 || ^10" } }, "sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA=="], - - "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], - - "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], - - "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], - - "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], - - "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], - - "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], - - "execa": ["execa@1.0.0", "", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA=="], - - "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], - - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - - "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], - - "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - - "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], - - "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - - "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], - - "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], - - "fmix": ["fmix@0.1.0", "", { "dependencies": { "imul": "^1.0.0" } }, "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w=="], - - "fs-temp": ["fs-temp@1.2.1", "", { "dependencies": { "random-path": "^0.1.0" } }, "sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w=="], - - "fs-xattr": ["fs-xattr@0.3.1", "", { "os": "!win32" }, "sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA=="], - - "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - - "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], - - "generate-object-property": ["generate-object-property@1.2.0", "", { "dependencies": { "is-property": "^1.0.0" } }, "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ=="], - - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - - "get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], - - "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - - "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], - - "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], - - "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - - "image-size": ["image-size@0.7.5", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g=="], - - "imul": ["imul@1.0.1", "", {}, "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA=="], - - "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - - "is-my-ip-valid": ["is-my-ip-valid@1.0.1", "", {}, "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg=="], - - "is-my-json-valid": ["is-my-json-valid@2.20.6", "", { "dependencies": { "generate-function": "^2.0.0", "generate-object-property": "^1.1.0", "is-my-ip-valid": "^1.0.0", "jsonpointer": "^5.0.0", "xtend": "^4.0.0" } }, "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw=="], - - "is-property": ["is-property@1.0.2", "", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], - - "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], - - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - - "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], - - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - - "json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], - - "jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="], - - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - - "ldrs": ["ldrs@1.1.9", "", {}, "sha512-JKVdzboxeZrKecA8ovi5iIDgs59wUrtJ+LDrHCgZecNrR0AJi2cJ3ZANJ+UCNS/sHRol73/jlypNCAMCXS+Ung=="], - - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - - "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], - - "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], - - "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], - - "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], - - "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="], - - "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="], - - "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="], - - "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="], - - "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="], - - "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="], - - "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="], - - "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], - - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], - - "lucide-react": ["lucide-react@1.26.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-raglYVR2+VkMfJL158krjVmE+rV5ST2lzA/KQm1FRSjMHT4MnWaegHxoVEpmc2So3nOEhp9oGejJwAPX8MoAjg=="], - - "macos-alias": ["macos-alias@0.2.12", "", { "dependencies": { "nan": "^2.4.0" }, "os": "darwin" }, "sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw=="], - - "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], - - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - - "murmur-32": ["murmur-32@0.2.0", "", { "dependencies": { "encode-utf8": "^1.0.3", "fmix": "^0.1.0", "imul": "^1.0.0" } }, "sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q=="], - - "nan": ["nan@2.27.0", "", {}, "sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ=="], - - "nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="], - - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - - "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], - - "node-releases": ["node-releases@2.0.38", "", {}, "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw=="], - - "npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="], - - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], - - "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], - - "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], - - "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - - "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - - "parse-color": ["parse-color@1.0.0", "", { "dependencies": { "color-convert": "~0.5.0" } }, "sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw=="], - - "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - - "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - - "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], - - "postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="], - - "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - - "prettier": ["prettier@3.9.6", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g=="], - - "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - - "random-path": ["random-path@0.1.2", "", { "dependencies": { "base32-encode": "^0.1.0 || ^1.0.0", "murmur-32": "^0.1.0 || ^0.2.0" } }, "sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw=="], - - "react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="], - - "react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="], - - "repeat-string": ["repeat-string@1.6.1", "", {}, "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="], - - "rolldown": ["rolldown@1.1.5", "", { "dependencies": { "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.5", "@rolldown/binding-darwin-arm64": "1.1.5", "@rolldown/binding-darwin-x64": "1.1.5", "@rolldown/binding-freebsd-x64": "1.1.5", "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", "@rolldown/binding-linux-arm64-gnu": "1.1.5", "@rolldown/binding-linux-arm64-musl": "1.1.5", "@rolldown/binding-linux-ppc64-gnu": "1.1.5", "@rolldown/binding-linux-s390x-gnu": "1.1.5", "@rolldown/binding-linux-x64-gnu": "1.1.5", "@rolldown/binding-linux-x64-musl": "1.1.5", "@rolldown/binding-openharmony-arm64": "1.1.5", "@rolldown/binding-wasm32-wasi": "1.1.5", "@rolldown/binding-win32-arm64-msvc": "1.1.5", "@rolldown/binding-win32-x64-msvc": "1.1.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA=="], - - "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], - - "semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], - - "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - - "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - - "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="], - - "strip-eof": ["strip-eof@1.0.0", "", {}, "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q=="], - - "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], - - "tn1150": ["tn1150@0.1.0", "", { "dependencies": { "unorm": "^1.4.1" } }, "sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w=="], - - "to-data-view": ["to-data-view@1.1.0", "", {}, "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ=="], - - "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], - - "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - - "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], - - "typescript-eslint": ["typescript-eslint@8.65.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.65.0", "@typescript-eslint/parser": "8.65.0", "@typescript-eslint/typescript-estree": "8.65.0", "@typescript-eslint/utils": "8.65.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA=="], - - "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - - "unorm": ["unorm@1.6.0", "", {}, "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA=="], - - "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], - - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - - "vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="], - - "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], - - "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], - - "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - - "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - - "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - - "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], - - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - - "@typescript-eslint/typescript-estree/semver": ["semver@7.8.0", "", { "bin": "bin/semver.js" }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], - - "bun-types/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], - - "eslint-plugin-react-hooks/@babel/parser": ["@babel/parser@7.29.3", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA=="], - - "execa/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], - - "npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "eslint-plugin-react-hooks/@babel/parser/@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], - - "execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "execa/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "execa/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - - "execa/cross-spawn/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], - - "eslint-plugin-react-hooks/@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], - - "eslint-plugin-react-hooks/@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], - - "execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - } -} diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 5330d14..181dff5 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -328,7 +328,7 @@ precise local timezone gives most of the location back. against three unrelated native APIs, and only one of them compiles on whatever machine you are sitting at. Two safety nets: -- **`bun run check:platforms`** builds and tests all three locally. Linux goes +- **`pnpm run check:platforms`** builds and tests all three locally. Linux goes through the same Docker image as `scripts/build-linux.sh`. Windows is a cross _type-check_: the whole crate cannot cross-compile (llama.cpp needs a C++ toolchain) but `cargo check` never links, so the script assembles a scratch diff --git a/docs/SIGNING.md b/docs/SIGNING.md index 307e98d..388540d 100644 --- a/docs/SIGNING.md +++ b/docs/SIGNING.md @@ -84,9 +84,10 @@ user to override their OS's security check is the wrong first impression. ``` `spctl` must report `accepted source=Notarized Developer ID`. -**Note on the DMG.** The installer is built by `scripts/make-styled-dmg.sh` via -`appdmg`, not by Tauri's bundler, so the `.dmg` itself needs signing and stapling as -a separate step after it is assembled — signing the `.app` alone is not enough. +**Note on the DMG.** The installer is built by `scripts/make-styled-dmg.sh` with +native macOS disk-image tools, not by Tauri's bundler, so the `.dmg` itself needs +signing and stapling as a separate step after it is assembled. Signing the `.app` +alone is not enough. ## Windows — Azure Trusted Signing @@ -131,7 +132,7 @@ Install button reports `unconfigured` — _"This build has no update signing key anyone with the private key can push an update to every ÆTHER install. ```bash - bun run tauri signer generate -w ~/.tauri/aether-updater.key + pnpm run tauri signer generate -w ~/.tauri/aether-updater.key ``` This prints a public key and writes the private key to that path. **Back both up diff --git a/eslint.config.mjs b/eslint.config.mjs index d0be451..17b1e1e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -16,8 +16,8 @@ export default defineConfig( '.design-sync/**', '.ds-sync/**', 'aether-ds/**', - 'ds-bundle/**' - ] + 'ds-bundle/**', + ], }, js.configs.recommended, tseslint.configs.recommended, @@ -25,12 +25,12 @@ export default defineConfig( files: ['**/*.tsx'], plugins: { 'react-hooks': eslintPluginReactHooks, - 'react-refresh': eslintPluginReactRefresh + 'react-refresh': eslintPluginReactRefresh, }, rules: { ...eslintPluginReactHooks.configs.recommended.rules, - ...eslintPluginReactRefresh.configs.vite.rules - } + ...eslintPluginReactRefresh.configs.vite.rules, + }, }, - eslintConfigPrettier + eslintConfigPrettier, ) diff --git a/package.json b/package.json index 25bee97..6a085dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aether-browser", - "version": "1.1.2", + "version": "1.1.3", "productName": "ÆTHER", "description": "Local AI-powered engine and knowledge hub", "keywords": [ @@ -14,25 +14,28 @@ "author": "canpixel.com", "homepage": "https://canpixel.com", "license": "PolyForm-Strict-1.0.0", + "type": "module", + "packageManager": "pnpm@11.24.0+sha512.bd27e345e976dcb0be0b7a1228217b049a817e21b1f355c90dbe7dc46671895a8bc1e6d06c24554505ea93ea0b45f489a27ec1bfbc8de6a9659fca0f16fa0000", "scripts": { "format": "prettier --write .", "lint": "eslint --cache .", "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false", "typecheck:tauri": "cargo check --manifest-path src-tauri/Cargo.toml", - "typecheck": "bun run typecheck:web && bun run typecheck:tauri", - "test:web": "bun test src/renderer/src/utils/evidence-bundle.test.ts src/renderer/src/utils/extraction-receipt.test.ts", - "test": "cargo test --manifest-path src-tauri/Cargo.toml --lib && bun run test:web", + "typecheck": "pnpm run typecheck:web && pnpm run typecheck:tauri", + "test:web": "node --test 'src/renderer/src/**/*.test.ts'", + "test": "cargo test --manifest-path src-tauri/Cargo.toml --lib && pnpm run test:web", "check:platforms": "bash scripts/check-platforms.sh", - "version:bump": "bun scripts/bump-version.ts", - "version:check": "bun scripts/bump-version.ts --check", - "release": "bun scripts/release.ts", + "audit": "pnpm audit", + "version:bump": "node scripts/bump-version.ts", + "version:check": "node scripts/bump-version.ts --check", + "release": "node scripts/release.ts", "start": "tauri dev", "dev": "tauri dev", "dev:vite": "vite", "build:vite": "vite build", "prepare:dmg-background": "bash scripts/prepare-dmg-background.sh", - "build": "bun run typecheck && tauri build --bundles app && bun run dmg", - "build:macos-universal": "bun run typecheck && tauri build --bundles app --target universal-apple-darwin && AETHER_TAURI_TARGET=universal-apple-darwin bun run dmg", + "build": "pnpm run typecheck && tauri build --bundles app && pnpm run dmg", + "build:macos-universal": "pnpm run typecheck && tauri build --bundles app --target universal-apple-darwin && AETHER_TAURI_TARGET=universal-apple-darwin pnpm run dmg", "dmg": "bash scripts/make-styled-dmg.sh", "android:init": "bash scripts/android.sh init", "android:dev": "bash scripts/android.sh dev", @@ -44,29 +47,26 @@ "linux:arm64:deb": "LINUX_BUNDLES=deb bash scripts/build-linux.sh", "linux:x64:build": "LINUX_DOCKER_PLATFORM=linux/amd64 LINUX_TARGET=x86_64-unknown-linux-gnu LINUX_ARCH_SLUG=x64 bash scripts/build-linux.sh", "linux:x64:deb": "LINUX_DOCKER_PLATFORM=linux/amd64 LINUX_TARGET=x86_64-unknown-linux-gnu LINUX_ARCH_SLUG=x64 LINUX_BUNDLES=deb bash scripts/build-linux.sh", - "build:desktop-local": "bun run build && bun run linux:arm64:build && bun run linux:x64:build", + "build:desktop-local": "pnpm run build && pnpm run linux:arm64:build && pnpm run linux:x64:build", "tauri": "tauri" }, - "overrides": { - "brace-expansion": "^5.0.7", - "@babel/core": "^7.29.1" - }, "dependencies": { "ldrs": "^1.1.9", "lucide-react": "^1.26.0" }, + "optionalDependencies": { + "@aether/dmg-metadata": "file:tools/dmg-metadata" + }, "devDependencies": { "@babel/core": "^8.0.1", - "brace-expansion": "^5.0.8", + "brace-expansion": "^5.0.9", "@eslint/js": "^9.39.5", "@tauri-apps/api": "^2.11.1", "@tauri-apps/cli": "^2.11.4", - "@types/bun": "^1.3.14", "@types/node": "^25.9.5", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.4", - "appdmg": "^0.6.6", "eslint": "^10.8.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-react-hooks": "^7.1.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9d4c07e --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1895 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + brace-expansion: ^5.0.9 + nanoid: ^3.3.18 + '@babel/core': ^7.29.1 + +importers: + + .: + dependencies: + ldrs: + specifier: ^1.1.9 + version: 1.1.9 + lucide-react: + specifier: ^1.26.0 + version: 1.30.0(react@19.2.8) + devDependencies: + '@babel/core': + specifier: ^7.29.1 + version: 7.29.7 + '@eslint/js': + specifier: ^9.39.5 + version: 9.39.5 + '@tauri-apps/api': + specifier: ^2.11.1 + version: 2.11.1 + '@tauri-apps/cli': + specifier: ^2.11.4 + version: 2.11.4 + '@types/node': + specifier: ^25.9.5 + version: 25.9.5 + '@types/react': + specifier: ^19.2.17 + version: 19.2.18 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.4(@types/react@19.2.18) + '@vitejs/plugin-react': + specifier: ^6.0.4 + version: 6.0.5(vite@8.2.1(@types/node@25.9.5)) + brace-expansion: + specifier: ^5.0.9 + version: 5.0.9 + eslint: + specifier: ^10.8.0 + version: 10.8.1 + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@10.8.1) + eslint-plugin-react-hooks: + specifier: ^7.1.1 + version: 7.1.1(eslint@10.8.1) + eslint-plugin-react-refresh: + specifier: ^0.5.3 + version: 0.5.3(eslint@10.8.1) + prettier: + specifier: ^3.9.6 + version: 3.9.6 + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) + typescript: + specifier: ^6.0.3 + version: 6.0.3 + typescript-eslint: + specifier: ^8.65.0 + version: 8.66.0(eslint@10.8.1)(typescript@6.0.3) + vite: + specifier: ^8.1.5 + version: 8.2.1(@types/node@25.9.5) + optionalDependencies: + '@aether/dmg-metadata': + specifier: file:tools/dmg-metadata + version: file:tools/dmg-metadata + +packages: + + '@aether/dmg-metadata@file:tools/dmg-metadata': + resolution: {directory: tools/dmg-metadata, type: directory} + os: [darwin] + hasBin: true + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.29.1 + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.23.5': + resolution: {integrity: sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/config-helpers@0.7.0': + resolution: {integrity: sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/core@1.2.1': + resolution: {integrity: sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/js@9.39.5': + resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@3.0.5': + resolution: {integrity: sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@eslint/plugin-kit@0.7.2': + resolution: {integrity: sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@oxc-project/types@0.143.0': + resolution: {integrity: sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==} + + '@rolldown/binding-android-arm64@1.2.3': + resolution: {integrity: sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.3': + resolution: {integrity: sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.3': + resolution: {integrity: sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.3': + resolution: {integrity: sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.3': + resolution: {integrity: sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.3': + resolution: {integrity: sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.2.3': + resolution: {integrity: sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.2.3': + resolution: {integrity: sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.2.3': + resolution: {integrity: sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.2.3': + resolution: {integrity: sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.2.3': + resolution: {integrity: sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.2.3': + resolution: {integrity: sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-win32-arm64-msvc@1.2.3': + resolution: {integrity: sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.3': + resolution: {integrity: sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@tauri-apps/api@2.11.1': + resolution: {integrity: sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==} + + '@tauri-apps/cli-darwin-arm64@2.11.4': + resolution: {integrity: sha512-1ryOF3ZhpZ/nemHV5zVwBQBz9jDGKmKPvWPADOhc83ig0P4bMc2iER4NbC6r9sjeIZ6RVQ4g3RZIYvezhcl4TQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@tauri-apps/cli-darwin-x64@2.11.4': + resolution: {integrity: sha512-uFsGQAAfuyz1k/yGLmkWfkBlgKAqZfxqlHmLWx81QU27RJWfmbNHCIq8T8w1e+VClleIuZUjpHWfoE4E3DLo3A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.4': + resolution: {integrity: sha512-IaHZn5CdBL21oUmjiVOS1ctw6Ip1O0pjp70FwOWmYz1myWe0SY96ZIj2FYf7pT0m8bI2h/hrs5ZbEXXh44/MkQ==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@tauri-apps/cli-linux-arm64-gnu@2.11.4': + resolution: {integrity: sha512-N41/ukTRVe6XSuUTESuFdGeOW2i7k62tK+6gHK5Kd5/q5RPvvi19GaWAVPPb9u95HSGmTChSolBfzynUsssFaA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tauri-apps/cli-linux-arm64-musl@2.11.4': + resolution: {integrity: sha512-v277UnT/fB64xAfSroL5N3Km3tLmvATWqJJw/wRI+g6o+HkeD0slyE7gOhNs1MbjE41R7bQOTxMVoL3aomUJmw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tauri-apps/cli-linux-riscv64-gnu@2.11.4': + resolution: {integrity: sha512-qqgNkQ2u1yZHxjhxsZaxUtRDW8dIqIYm33rx/mzwQv0SfY9x1B+iraj8vWeFiXjjSVVhEMepXSOts1TqPzvXNQ==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@tauri-apps/cli-linux-x64-gnu@2.11.4': + resolution: {integrity: sha512-2VRNWl84FOH0m2giiDkO2h0QXlcMJeX+zJDpI5kDIQAx6s+geF3v48F4DXfJez4GS/FdoDGnPnw1C2iYGbQ7bQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tauri-apps/cli-linux-x64-musl@2.11.4': + resolution: {integrity: sha512-o9GyhYor/nc7xarmwDE3ka2szuW3uuZzXjHWh64Q8YX5AtSgxdQkFWzrY4O8KiGtVNvFBI14H3Q49Qj5TOIP/A==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tauri-apps/cli-win32-arm64-msvc@2.11.4': + resolution: {integrity: sha512-ld5Ehb598m0VkYyylRPNeCFsBe/km0jxis6KgMpl3IGY6I/i1RwQXO05I1AsXUXO2WC6AvB/Lw4qTf/asiuEiQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@tauri-apps/cli-win32-ia32-msvc@2.11.4': + resolution: {integrity: sha512-12Hxi0XX/H5VFxO/bGgHkFWhml9VMgEOu9CidjeCeTNQ1l6fpUlbiGgSP7CLI3PFtW9/FfbeHieZ+kyWK5H7CA==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@tauri-apps/cli-win32-x64-msvc@2.11.4': + resolution: {integrity: sha512-+vDiqBIU5dMISg/wNvX3sF+ZHfgJGJ5T0AcO+EHNXV9GGAG+P5fzodlDXD3QdKCRgZxMoCm5PPvj3BqLNjBthw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@tauri-apps/cli@2.11.4': + resolution: {integrity: sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ==} + engines: {node: '>= 10'} + hasBin: true + + '@types/esrecurse@4.3.1': + resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@25.9.5': + resolution: {integrity: sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==} + + '@types/react-dom@19.2.4': + resolution: {integrity: sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.18': + resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} + + '@typescript-eslint/eslint-plugin@8.66.0': + resolution: {integrity: sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.66.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.66.0': + resolution: {integrity: sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.66.0': + resolution: {integrity: sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.66.0': + resolution: {integrity: sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.66.0': + resolution: {integrity: sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.66.0': + resolution: {integrity: sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.66.0': + resolution: {integrity: sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.66.0': + resolution: {integrity: sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.66.0': + resolution: {integrity: sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.66.0': + resolution: {integrity: sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react@6.0.5': + resolution: {integrity: sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + baseline-browser-mapping@2.11.13: + resolution: {integrity: sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + bplist-creator@0.0.8: + resolution: {integrity: sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==} + + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + + browserslist@4.28.8: + resolution: {integrity: sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + caniuse-lite@1.0.30001809: + resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + ds-store@0.1.6: + resolution: {integrity: sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==} + + electron-to-chromium@1.5.402: + resolution: {integrity: sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@10.1.8: + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-react-refresh@0.5.3: + resolution: {integrity: sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA==} + peerDependencies: + eslint: ^9 || ^10 + + eslint-scope@9.1.2: + resolution: {integrity: sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@10.8.1: + resolution: {integrity: sha512-wqA7W2jbsC/BnV9Iv1UZpKVFkO1AdNoSmYW8NWG4HNOBbkAMvIqDZ27pI2f07dqn583NcIC44ckjAcOXDL1QbQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@11.2.0: + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.6: + resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + engines: {node: '>= 4'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + ldrs@1.1.9: + resolution: {integrity: sha512-JKVdzboxeZrKecA8ovi5iIDgs59wUrtJ+LDrHCgZecNrR0AJi2cJ3ZANJ+UCNS/sHRol73/jlypNCAMCXS+Ung==} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lucide-react@1.30.0: + resolution: {integrity: sha512-tUIr2jXLbWpCkdtH8XP7P7YppM9ueWgTky99lpWDY6z5REs6B+O6ZQ3U5tHkUUY59ANyOv/PBcs8E4Fe3KO3eA==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + macos-alias@0.2.12: + resolution: {integrity: sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw==} + os: [darwin] + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nan@2.28.0: + resolution: {integrity: sha512-fTsDz99OTq2sVePhGdp4qQhggZFtKr64ZNVyVajRKtMOkJxYekplBh577PiJB12v/D3s2E5cGtOI45LWp6rnLQ==} + + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.53: + resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==} + engines: {node: '>=18'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.9.6: + resolution: {integrity: sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==} + engines: {node: '>=14'} + hasBin: true + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} + peerDependencies: + react: ^19.2.8 + + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} + engines: {node: '>=0.10.0'} + + rolldown@1.2.3: + resolution: {integrity: sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stream-buffers@2.2.0: + resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} + engines: {node: '>= 0.10.0'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tn1150@0.1.0: + resolution: {integrity: sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w==} + engines: {node: '>=0.12'} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript-eslint@8.66.0: + resolution: {integrity: sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + unorm@1.6.0: + resolution: {integrity: sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==} + engines: {node: '>= 0.4.0'} + + update-browserslist-db@1.3.0: + resolution: {integrity: sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + vite@8.2.1: + resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.4.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + +snapshots: + + '@aether/dmg-metadata@file:tools/dmg-metadata': + dependencies: + ds-store: 0.1.6 + optional: true + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.8 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@eslint-community/eslint-utils@4.10.1(eslint@10.8.1)': + dependencies: + eslint: 10.8.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.23.5': + dependencies: + '@eslint/object-schema': 3.0.5 + debug: 4.4.3 + minimatch: 10.2.6 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.7.0': + dependencies: + '@eslint/core': 1.2.1 + + '@eslint/core@1.2.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/js@9.39.5': {} + + '@eslint/object-schema@3.0.5': {} + + '@eslint/plugin-kit@0.7.2': + dependencies: + '@eslint/core': 1.2.1 + levn: 0.4.1 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@oxc-project/types@0.143.0': {} + + '@rolldown/binding-android-arm64@1.2.3': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.3': + optional: true + + '@rolldown/binding-darwin-x64@1.2.3': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.3': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.3': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.3': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.3': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.3': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.3': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.3': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.3': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@tauri-apps/api@2.11.1': {} + + '@tauri-apps/cli-darwin-arm64@2.11.4': + optional: true + + '@tauri-apps/cli-darwin-x64@2.11.4': + optional: true + + '@tauri-apps/cli-linux-arm-gnueabihf@2.11.4': + optional: true + + '@tauri-apps/cli-linux-arm64-gnu@2.11.4': + optional: true + + '@tauri-apps/cli-linux-arm64-musl@2.11.4': + optional: true + + '@tauri-apps/cli-linux-riscv64-gnu@2.11.4': + optional: true + + '@tauri-apps/cli-linux-x64-gnu@2.11.4': + optional: true + + '@tauri-apps/cli-linux-x64-musl@2.11.4': + optional: true + + '@tauri-apps/cli-win32-arm64-msvc@2.11.4': + optional: true + + '@tauri-apps/cli-win32-ia32-msvc@2.11.4': + optional: true + + '@tauri-apps/cli-win32-x64-msvc@2.11.4': + optional: true + + '@tauri-apps/cli@2.11.4': + optionalDependencies: + '@tauri-apps/cli-darwin-arm64': 2.11.4 + '@tauri-apps/cli-darwin-x64': 2.11.4 + '@tauri-apps/cli-linux-arm-gnueabihf': 2.11.4 + '@tauri-apps/cli-linux-arm64-gnu': 2.11.4 + '@tauri-apps/cli-linux-arm64-musl': 2.11.4 + '@tauri-apps/cli-linux-riscv64-gnu': 2.11.4 + '@tauri-apps/cli-linux-x64-gnu': 2.11.4 + '@tauri-apps/cli-linux-x64-musl': 2.11.4 + '@tauri-apps/cli-win32-arm64-msvc': 2.11.4 + '@tauri-apps/cli-win32-ia32-msvc': 2.11.4 + '@tauri-apps/cli-win32-x64-msvc': 2.11.4 + + '@types/esrecurse@4.3.1': {} + + '@types/estree@1.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@25.9.5': + dependencies: + undici-types: 7.24.6 + + '@types/react-dom@19.2.4(@types/react@19.2.18)': + dependencies: + '@types/react': 19.2.18 + + '@types/react@19.2.18': + dependencies: + csstype: 3.2.3 + + '@typescript-eslint/eslint-plugin@8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.1)(typescript@6.0.3))(eslint@10.8.1)(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/type-utils': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.66.0 + eslint: 10.8.1 + ignore: 7.0.6 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.66.0(eslint@10.8.1)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.66.0 + debug: 4.4.3 + eslint: 10.8.1 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.66.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3) + '@typescript-eslint/types': 8.66.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.66.0': + dependencies: + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/visitor-keys': 8.66.0 + + '@typescript-eslint/tsconfig-utils@8.66.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.66.0(eslint@10.8.1)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + debug: 4.4.3 + eslint: 10.8.1 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.66.0': {} + + '@typescript-eslint/typescript-estree@8.66.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.66.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.66.0(typescript@6.0.3) + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/visitor-keys': 8.66.0 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.66.0(eslint@10.8.1)(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1) + '@typescript-eslint/scope-manager': 8.66.0 + '@typescript-eslint/types': 8.66.0 + '@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3) + eslint: 10.8.1 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.66.0': + dependencies: + '@typescript-eslint/types': 8.66.0 + eslint-visitor-keys: 5.0.1 + + '@vitejs/plugin-react@6.0.5(vite@8.2.1(@types/node@25.9.5))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.2.1(@types/node@25.9.5) + + acorn-jsx@5.3.2(acorn@8.18.0): + dependencies: + acorn: 8.18.0 + + acorn@8.18.0: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + balanced-match@4.0.4: {} + + baseline-browser-mapping@2.11.13: {} + + bplist-creator@0.0.8: + dependencies: + stream-buffers: 2.2.0 + optional: true + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + + browserslist@4.28.8: + dependencies: + baseline-browser-mapping: 2.11.13 + caniuse-lite: 1.0.30001809 + electron-to-chromium: 1.5.402 + node-releases: 2.0.53 + update-browserslist-db: 1.3.0(browserslist@4.28.8) + + caniuse-lite@1.0.30001809: {} + + convert-source-map@2.0.0: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + detect-libc@2.1.2: {} + + ds-store@0.1.6: + dependencies: + bplist-creator: 0.0.8 + macos-alias: 0.2.12 + tn1150: 0.1.0 + optional: true + + electron-to-chromium@1.5.402: {} + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@10.1.8(eslint@10.8.1): + dependencies: + eslint: 10.8.1 + + eslint-plugin-react-hooks@7.1.1(eslint@10.8.1): + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.8 + eslint: 10.8.1 + hermes-parser: 0.25.1 + zod: 4.4.3 + zod-validation-error: 4.0.2(zod@4.4.3) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-refresh@0.5.3(eslint@10.8.1): + dependencies: + eslint: 10.8.1 + + eslint-scope@9.1.2: + dependencies: + '@types/esrecurse': 4.3.1 + '@types/estree': 1.0.9 + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@10.8.1: + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@10.8.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.23.5 + '@eslint/config-helpers': 0.7.0 + '@eslint/core': 1.2.1 + '@eslint/plugin-kit': 0.7.2 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 9.1.2 + eslint-visitor-keys: 5.0.1 + espree: 11.2.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + minimatch: 10.2.6 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@11.2.0: + dependencies: + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) + eslint-visitor-keys: 5.0.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fdir@6.5.0(picomatch@4.0.5): + optionalDependencies: + picomatch: 4.0.5 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.4 + keyv: 4.5.4 + + flatted@3.4.4: {} + + fsevents@2.3.3: + optional: true + + gensync@1.0.0-beta.2: {} + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + ignore@5.3.2: {} + + ignore@7.0.6: {} + + imurmurhash@0.1.4: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + isexe@2.0.0: {} + + js-tokens@4.0.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + ldrs@1.1.9: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lucide-react@1.30.0(react@19.2.8): + dependencies: + react: 19.2.8 + + macos-alias@0.2.12: + dependencies: + nan: 2.28.0 + optional: true + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + + ms@2.1.3: {} + + nan@2.28.0: + optional: true + + nanoid@3.3.18: {} + + natural-compare@1.4.0: {} + + node-releases@2.0.53: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + picocolors@1.1.1: {} + + picomatch@4.0.5: {} + + postcss@8.5.26: + dependencies: + nanoid: 3.3.18 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@3.9.6: {} + + punycode@2.3.1: {} + + react-dom@19.2.8(react@19.2.8): + dependencies: + react: 19.2.8 + scheduler: 0.27.0 + + react@19.2.8: {} + + rolldown@1.2.3: + dependencies: + '@oxc-project/types': 0.143.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.2.3 + '@rolldown/binding-darwin-arm64': 1.2.3 + '@rolldown/binding-darwin-x64': 1.2.3 + '@rolldown/binding-freebsd-x64': 1.2.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.3 + '@rolldown/binding-linux-arm64-gnu': 1.2.3 + '@rolldown/binding-linux-arm64-musl': 1.2.3 + '@rolldown/binding-linux-ppc64-gnu': 1.2.3 + '@rolldown/binding-linux-s390x-gnu': 1.2.3 + '@rolldown/binding-linux-x64-gnu': 1.2.3 + '@rolldown/binding-linux-x64-musl': 1.2.3 + '@rolldown/binding-openharmony-arm64': 1.2.3 + '@rolldown/binding-win32-arm64-msvc': 1.2.3 + '@rolldown/binding-win32-x64-msvc': 1.2.3 + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.8.5: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + source-map-js@1.2.1: {} + + stream-buffers@2.2.0: + optional: true + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.5) + picomatch: 4.0.5 + + tn1150@0.1.0: + dependencies: + unorm: 1.6.0 + optional: true + + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript-eslint@8.66.0(eslint@10.8.1)(typescript@6.0.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.66.0(@typescript-eslint/parser@8.66.0(eslint@10.8.1)(typescript@6.0.3))(eslint@10.8.1)(typescript@6.0.3) + '@typescript-eslint/parser': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + '@typescript-eslint/typescript-estree': 8.66.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.66.0(eslint@10.8.1)(typescript@6.0.3) + eslint: 10.8.1 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + typescript@6.0.3: {} + + undici-types@7.24.6: {} + + unorm@1.6.0: + optional: true + + update-browserslist-db@1.3.0(browserslist@4.28.8): + dependencies: + browserslist: 4.28.8 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + vite@8.2.1(@types/node@25.9.5): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.5 + postcss: 8.5.26 + rolldown: 1.2.3 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.9.5 + fsevents: 2.3.3 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + zod-validation-error@4.0.2(zod@4.4.3): + dependencies: + zod: 4.4.3 + + zod@4.4.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..78ebc71 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,47 @@ +# pnpm settings for ÆTHER. +# +# This file replaces bunfig.toml and the npm-style `overrides` / +# `patchedDependencies` blocks that used to live in package.json. pnpm reads +# NONE of those: a top-level `overrides` key is an npm/bun convention that pnpm +# silently ignores, so anything left there is decoration, not enforcement. +# Everything that must actually bind lives here. + +# Refuse to install any package version published less than 3 days ago. +# +# Carried over from bunfig.toml. This is a supply-chain measure, not a stability +# one. The dangerous window for a compromised or typosquatted release is the +# first hours after publish, before registries, scanners, and other maintainers +# have noticed. Three days does not make a package safe; it means someone else +# is very likely to have hit the bad version first. +# +# NOTE THE UNIT: bun's minimumReleaseAge is in SECONDS (259200), pnpm's is in +# MINUTES. 3 days = 4320. Copying bun's 259200 across would freeze installs for +# 180 days. +minimumReleaseAge: 4320 + +# Packages allowed to bypass the wait. Deliberately empty. +# +# The reason to add one is a genuine emergency -- a security patch needed before +# the window closes -- and in that case prefer a one-off +# `pnpm install --minimum-release-age=0` over a permanent hole here, so the +# exemption expires with the command instead of living in the repo. +minimumReleaseAgeExclude: [] + +overrides: + # CVE-2026-14257 mitigation bypass (DoS via unbounded intermediate arrays). + # Reaches us through eslint > @eslint/config-array > minimatch and through + # typescript-eslint > ... > minimatch. + brace-expansion: ^5.0.9 + # GHSA-2v37-7h3g-55p8: custom generators loop forever when size is zero. + # Transitive via vite > postcss. Pinned to the patched 3.x line because that + # is the major postcss consumes; do not "upgrade" this to 6.x. + nanoid: ^3.3.18 + # Pre-existing pin, predates the pnpm move. Keeps the toolchain on Babel 7 + # even though a devDependency range would otherwise admit 8.x. + '@babel/core': ^7.29.1 + +# Native build scripts are blocked by default. The DS_Store writer needs +# macos-alias to encode the background image path on macOS. Everything else +# stays blocked. +allowBuilds: + macos-alias: true diff --git a/scripts/android.sh b/scripts/android.sh index d4159bd..e0b292e 100755 --- a/scripts/android.sh +++ b/scripts/android.sh @@ -48,4 +48,4 @@ if [ "${1:-}" = "build" ]; then esac fi -exec bun tauri android "${args[@]}" +exec pnpm exec tauri android "${args[@]}" diff --git a/scripts/build-linux.sh b/scripts/build-linux.sh index e265fb3..fba096a 100755 --- a/scripts/build-linux.sh +++ b/scripts/build-linux.sh @@ -4,8 +4,8 @@ set -euo pipefail # Build a Linux Tauri package inside a Docker container, so Linux-only toolchains # and dependencies never touch the host. Arch is parametrized; defaults to arm64. # -# bun run linux:arm64:build # aarch64 .deb -# bun run linux:x64:build # x86_64 .deb +# pnpm run linux:arm64:build # aarch64 .deb +# pnpm run linux:x64:build # x86_64 .deb # # Overridable via env: # LINUX_DOCKER_PLATFORM (default linux/arm64) docker --platform @@ -36,14 +36,14 @@ docker run --rm --platform "${PLATFORM}" \ -v "aether-linux-${ARCH_SLUG}-node-modules:/work/node_modules" \ -v "aether-linux-${ARCH_SLUG}-cargo:/root/.cargo" \ -v "aether-linux-${ARCH_SLUG}-rustup:/root/.rustup" \ - -v "aether-linux-${ARCH_SLUG}-bun:/root/.bun" \ + -v "aether-linux-${ARCH_SLUG}-pnpm:/root/.local/share/pnpm" \ -w /work \ "${IMAGE}" \ bash -lc ' set -euo pipefail export DEBIAN_FRONTEND=noninteractive - export PATH="/root/.bun/bin:/root/.cargo/bin:${PATH}" + export PATH="/root/.local/share/pnpm:/root/.cargo/bin:${PATH}" apt-get update apt-get install -y --no-install-recommends \ @@ -64,10 +64,27 @@ docker run --rm --platform "${PLATFORM}" \ libayatana-appindicator3-dev \ librsvg2-dev - if ! command -v bun >/dev/null 2>&1; then - curl -fsSL https://bun.sh/install | bash + if ! command -v node >/dev/null 2>&1; then + # Ubuntu 24.04 ships Node 18 in apt, but the release scripts and + # `node --test` rely on the native TypeScript support added in 22.6+, so + # take an official build rather than the distro one. + NODE_VERSION="v24.14.1" + case "$(uname -m)" in + aarch64) NODE_ARCH="arm64" ;; + x86_64) NODE_ARCH="x64" ;; + *) echo "unsupported arch for node install: $(uname -m)" >&2; exit 1 ;; + esac + curl -fsSL "https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-${NODE_ARCH}.tar.xz" \ + | tar -xJ -C /usr/local --strip-components=1 fi + # corepack reads the pinned version out of the "packageManager" field in + # package.json, so the container runs exactly the pnpm the repo declares + # instead of whatever is newest. (No apostrophes in this block: the whole + # script is passed to bash -lc inside single quotes.) + export PNPM_HOME="/root/.local/share/pnpm" + corepack enable pnpm --install-directory "${PNPM_HOME}" + if ! command -v rustup >/dev/null 2>&1; then curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal fi @@ -75,9 +92,9 @@ docker run --rm --platform "${PLATFORM}" \ rustup default stable rustup target add "${LINUX_TARGET}" - bun install --frozen-lockfile - bun run typecheck:web - bun run tauri build --target "${LINUX_TARGET}" --bundles "${LINUX_BUNDLES}" --ci + pnpm install --frozen-lockfile + pnpm run typecheck:web + pnpm run tauri build --target "${LINUX_TARGET}" --bundles "${LINUX_BUNDLES}" --ci if compgen -G "${CARGO_TARGET_DIR}/${LINUX_TARGET}/release/bundle/deb/*.deb" > /dev/null; then scripts/normalize-deb-package.sh "${CARGO_TARGET_DIR}/${LINUX_TARGET}/release/bundle/deb/"*.deb diff --git a/scripts/bump-version.ts b/scripts/bump-version.ts index 0c6cd33..3186268 100644 --- a/scripts/bump-version.ts +++ b/scripts/bump-version.ts @@ -1,5 +1,4 @@ -#!/usr/bin/env bun -/// +#!/usr/bin/env node import { readFile, writeFile } from 'node:fs/promises' @@ -18,15 +17,15 @@ const versionArg = args.find((arg: string) => !arg.startsWith('-')) function usage(): void { console.error('Usage:') - console.error(' bun run version:bump 1.2.3') - console.error(' bun run version:check') + console.error(' pnpm run version:bump 1.2.3') + console.error(' pnpm run version:check') process.exit(1) } function assertVersion(version: string): void { if (!VERSION_PATTERN.test(version)) { console.error( - `Invalid version "${version}". Use SemVer without a leading "v", for example 1.2.3.` + `Invalid version "${version}". Use SemVer without a leading "v", for example 1.2.3.`, ) process.exit(1) } @@ -60,7 +59,7 @@ function updateCargoPackageVersion(content: string, version: string): string { function readCargoLockPackageVersion(content: string): string { const match = content.match( - /^\[\[package\]\]\s*\nname\s*=\s*"aether"\s*\nversion\s*=\s*"([^"]+)"/m + /^\[\[package\]\]\s*\nname\s*=\s*"aether"\s*\nversion\s*=\s*"([^"]+)"/m, ) if (!match) throw new Error('Could not find aether package version in src-tauri/Cargo.lock') return match[1] @@ -69,7 +68,7 @@ function readCargoLockPackageVersion(content: string): string { function updateCargoLockPackageVersion(content: string, version: string): string { const next = content.replace( /^(\[\[package\]\]\s*\nname\s*=\s*"aether"\s*\nversion\s*=\s*)"([^"]+)"/m, - `$1"${version}"` + `$1"${version}"`, ) if (next === content) { throw new Error('Could not update aether package version in src-tauri/Cargo.lock') @@ -82,7 +81,7 @@ async function readVersions(): Promise { readFile('package.json', 'utf8'), readFile('src-tauri/Cargo.toml', 'utf8'), readFile('src-tauri/Cargo.lock', 'utf8'), - readFile('src-tauri/tauri.conf.json', 'utf8') + readFile('src-tauri/tauri.conf.json', 'utf8'), ]) const packageJson = JSON.parse(packageRaw) as { version?: string } const tauriConfig = JSON.parse(tauriRaw) as { version?: string } @@ -94,7 +93,7 @@ async function readVersions(): Promise { packageJson: packageJson.version, cargoToml: readCargoPackageVersion(cargoRaw), cargoLock: readCargoLockPackageVersion(cargoLockRaw), - tauriConfig: tauriConfig.version + tauriConfig: tauriConfig.version, } } @@ -117,7 +116,7 @@ async function bumpVersion(version: string): Promise { readFile('package.json', 'utf8'), readFile('src-tauri/Cargo.toml', 'utf8'), readFile('src-tauri/Cargo.lock', 'utf8'), - readFile('src-tauri/tauri.conf.json', 'utf8') + readFile('src-tauri/tauri.conf.json', 'utf8'), ]) const packageJson = JSON.parse(packageRaw) as { version: string } @@ -129,7 +128,7 @@ async function bumpVersion(version: string): Promise { writeFile('package.json', `${JSON.stringify(packageJson, null, 2)}\n`), writeFile('src-tauri/Cargo.toml', updateCargoPackageVersion(cargoRaw, version)), writeFile('src-tauri/Cargo.lock', updateCargoLockPackageVersion(cargoLockRaw, version)), - writeFile('src-tauri/tauri.conf.json', `${JSON.stringify(tauriConfig, null, 2)}\n`) + writeFile('src-tauri/tauri.conf.json', `${JSON.stringify(tauriConfig, null, 2)}\n`), ]) console.log(`Synced app version to ${version}`) diff --git a/scripts/make-styled-dmg.sh b/scripts/make-styled-dmg.sh index 30b7129..8f0229c 100755 --- a/scripts/make-styled-dmg.sh +++ b/scripts/make-styled-dmg.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# make-styled-dmg.sh — build a *reliably styled* ÆTHER installer DMG. +# make-styled-dmg.sh: build a reliably styled ÆTHER installer DMG. # # Why this exists: # Tauri's built-in DMG bundler copies the background PNG into the image but @@ -9,16 +9,14 @@ # silently reverts to a solid-colour background when the build runs without GUI # Finder automation (sandbox / headless tool runners) or when a stale volume of # the same name is mounted. The shipped .DS_Store then carries only -# `backgroundColor*` and no `backgroundImageAlias` — i.e. a "stock" installer. +# `backgroundColor*` and no `backgroundImageAlias`, producing a stock installer. # -# appdmg writes the .DS_Store background alias directly (via the `ds-store` -# library), so it does NOT depend on Finder and is deterministic / CI-safe. -# This wrapper derives the layout from tauri.conf.json (single source of truth), -# runs appdmg against the already-built .app, and VERIFIES that the picture -# background actually landed before declaring success. +# This wrapper writes the .DS_Store background alias directly, builds the disk +# image with native macOS tools, and verifies the result. It does not depend on +# Finder automation or the vulnerable appdmg > image-size dependency chain. # -# Usage: bun run dmg (expects `tauri build --bundles app` to have produced the .app) -# AETHER_TAURI_TARGET=universal-apple-darwin bun run dmg +# Usage: pnpm run dmg (expects `tauri build --bundles app` to have produced the .app) +# AETHER_TAURI_TARGET=universal-apple-darwin pnpm run dmg # (expects `tauri build --target universal-apple-darwin`) set -euo pipefail @@ -33,7 +31,7 @@ else fi APP="${BUNDLE_DIR}/macos/${VOLNAME}.app" OUT_DIR="${BUNDLE_DIR}/dmg" -VERSION="$(bun -e 'console.log(require("./src-tauri/tauri.conf.json").version)')" +VERSION="$(node -e 'console.log(require("./src-tauri/tauri.conf.json").version)')" if [[ "${AETHER_TAURI_TARGET:-}" == "universal-apple-darwin" ]]; then ARCH="universal" else @@ -47,38 +45,10 @@ OUT="${OUT_DIR}/${VOLNAME}_${VERSION}_${ARCH}.dmg" BG_PNG="build/dmg-background.png" BG_TIFF="build/dmg-background.tiff" -[[ -d "$APP" ]] || { echo "ERROR: built app not found at $APP — run 'bun run build' (or 'tauri build') first." >&2; exit 1; } +[[ "$(uname -s)" == "Darwin" ]] || { echo "ERROR: DMG creation requires macOS." >&2; exit 1; } +[[ -d "$APP" ]] || { echo "ERROR: built app not found at $APP. Run 'pnpm run build' first." >&2; exit 1; } bash scripts/prepare-dmg-background.sh - -# Derive everything from tauri.conf.json so the DMG never drifts from config. -SPEC="$(mktemp -u -t aether-appdmg).json" -trap 'rm -f "$SPEC" 2>/dev/null || true' EXIT -BUNDLE_DIR="$BUNDLE_DIR" SPEC="$SPEC" bun -e ' - const fs = require("fs"); - const path = require("path"); - const conf = require("./src-tauri/tauri.conf.json"); - const d = conf.bundle.macOS.dmg; - // tauri.conf paths are relative to src-tauri/; resolve to repo root. - const fromTauri = (p) => path.resolve("src-tauri", p); - const spec = { - title: conf.productName, - icon: fromTauri(conf.bundle.icon.find((i) => i.endsWith(".icns")) || "../build/icon.icns"), - background: path.resolve("build/dmg-background.png"), - "background-color": "#effbff", - "icon-size": 128, - format: "UDZO", - window: { size: { width: d.windowSize.width, height: d.windowSize.height } }, - contents: [ - { x: d.appPosition.x, y: d.appPosition.y, type: "file", - path: path.resolve(process.env.BUNDLE_DIR + "/macos/" + conf.productName + ".app") }, - { x: d.applicationFolderPosition.x, y: d.applicationFolderPosition.y, type: "link", path: "/Applications" }, - ], - }; - fs.writeFileSync(process.env.SPEC, JSON.stringify(spec, null, 2)); - console.log(`window ${spec.window.size.width}x${spec.window.size.height} app(${d.appPosition.x},${d.appPosition.y}) apps(${d.applicationFolderPosition.x},${d.applicationFolderPosition.y})`); -' -echo "==> spec derived from tauri.conf.json" echo "==> background rendered from SVG: $BG_PNG + $BG_TIFF" # Hygiene: clear any stale mounts of the same volume name. @@ -101,13 +71,72 @@ done < <(find /Volumes -maxdepth 1 \( -name "${VOLNAME}" -o -name "${VOLNAME} *" mkdir -p "$OUT_DIR" rm -f "$OUT" -echo "==> building DMG with appdmg" -bunx appdmg "$SPEC" "$OUT" + +WORK_DIR="$(mktemp -d -t aether-dmg)" +TEMP_IMAGE="${WORK_DIR}/writable.dmg" +RW_MOUNT="" +VERIFY_DEV="" + +cleanup() { + if [[ -n "$VERIFY_DEV" ]]; then + hdiutil detach "$VERIFY_DEV" -force >/dev/null 2>&1 || true + fi + if [[ -n "$RW_MOUNT" ]]; then + hdiutil detach "$RW_MOUNT" -force >/dev/null 2>&1 || true + fi + rm -f "$TEMP_IMAGE" + rmdir "$WORK_DIR" 2>/dev/null || true +} +trap cleanup EXIT + +detach_with_retry() { + local target="$1" + local delay + for delay in 1 2 4 8 16; do + if hdiutil detach "$target" >/dev/null 2>&1; then + return 0 + fi + sleep "$delay" + done + return 1 +} + +# Use 1.5 times the app size plus 32 MiB for image metadata, the background, and +# filesystem block overhead. +APP_MB="$(du -sm "$APP" | awk '{print $1}')" +IMAGE_MB=$(( (APP_MB * 3 + 1) / 2 + 32 )) + +echo "==> creating ${IMAGE_MB} MiB writable image" +hdiutil create "$TEMP_IMAGE" -ov -fs HFS+ -size "${IMAGE_MB}m" -volname "$VOLNAME" >/dev/null +ATTACH_OUTPUT="$(hdiutil attach "$TEMP_IMAGE" -nobrowse -noverify -noautoopen)" +RW_MOUNT="$(printf '%s\n' "$ATTACH_OUTPUT" | awk '/\/Volumes\// {i=index($0,"/Volumes/"); print substr($0,i); exit}')" +[[ -n "$RW_MOUNT" ]] || { echo "ERROR: failed to locate mounted writable image." >&2; exit 2; } + +mkdir "$RW_MOUNT/.background" +cp "$BG_TIFF" "$RW_MOUNT/.background/dmg-background.tiff" +cp -R "$APP" "$RW_MOUNT/${VOLNAME}.app" +ln -s /Applications "$RW_MOUNT/Applications" +cp build/icon.icns "$RW_MOUNT/.VolumeIcon.icns" + +# Set the custom-icon Finder flag without a native Node xattr dependency. +xattr -wx com.apple.FinderInfo \ + 0000000000000000040000000000000000000000000000000000000000000000 \ + "$RW_MOUNT" + +node_modules/.bin/aether-dmg-metadata "$RW_MOUNT" +sync +bless --folder "$RW_MOUNT" >/dev/null +detach_with_retry "$RW_MOUNT" || { echo "ERROR: could not detach writable image." >&2; exit 2; } +RW_MOUNT="" + +echo "==> compressing DMG" +hdiutil convert "$TEMP_IMAGE" -ov -format UDZO -imagekey zlib-level=9 -o "$OUT" >/dev/null # Verify the picture background is actually wired into .DS_Store (not a colour). echo "==> verifying baked background" -DEV=$(hdiutil attach -readonly -noautoopen -nobrowse "$OUT" | grep -E '^/dev/' | tail -1 | awk '{print $1}') -MNT=$(hdiutil info | awk -v d="$DEV" '$0 ~ d && /\/Volumes\// {i=index($0,"/Volumes/"); print substr($0,i); exit}') +VERIFY_OUTPUT="$(hdiutil attach -readonly -noautoopen -nobrowse "$OUT")" +VERIFY_DEV="$(printf '%s\n' "$VERIFY_OUTPUT" | awk '/^\/dev\// {print $1}' | tail -1)" +MNT="$(printf '%s\n' "$VERIFY_OUTPUT" | awk '/\/Volumes\// {i=index($0,"/Volumes/"); print substr($0,i); exit}')" ok=0 if [[ -n "$MNT" ]] \ && strings -a "$MNT/.DS_Store" 2>/dev/null | grep -q "backgroundImageAlias" \ @@ -115,7 +144,8 @@ if [[ -n "$MNT" ]] \ && tiffutil -info "$MNT/.background/dmg-background.tiff" | grep -q "Image Width: 1320 Image Length: 840"; then ok=1 fi -hdiutil detach "$DEV" -force >/dev/null 2>&1 || true +hdiutil detach "$VERIFY_DEV" -force >/dev/null 2>&1 || true +VERIFY_DEV="" if [[ "$ok" -ne 1 ]]; then echo "ERROR: DMG is missing a baked retina picture background." >&2 exit 2 diff --git a/scripts/release.ts b/scripts/release.ts index ceec737..737d258 100644 --- a/scripts/release.ts +++ b/scripts/release.ts @@ -1,9 +1,9 @@ -import { spawnSync } from 'bun' +import { spawnSync } from 'node:child_process' -const version = Bun.argv[2] +const version = process.argv[2] if (!version) { - console.error('❌ Please provide a version number. Example: bun run release 1.0.1') + console.error('❌ Please provide a version number. Example: pnpm run release 1.0.1') process.exit(1) } @@ -11,15 +11,22 @@ const versionTag = `v${version}` function runCommand(cmd: string[], description: string) { console.log(`\n🚀 ${description}...`) - const result = spawnSync(cmd, { stdout: 'inherit', stderr: 'inherit' }) - if (result.exitCode !== 0) { + const [command, ...args] = cmd + const result = spawnSync(command, args, { stdio: 'inherit' }) + if (result.error) { + console.error(`❌ Failed: ${description} — ${result.error.message}`) + process.exit(1) + } + // status is null when the child was killed by a signal; treat that as failure + // rather than exiting 0 and letting a half-done release look successful. + if (result.status !== 0) { console.error(`❌ Failed: ${description}`) - process.exit(result.exitCode) + process.exit(result.status ?? 1) } } -runCommand(['bun', 'run', 'version:bump', version], 'Bumping version') -runCommand(['bun', 'run', 'version:check'], 'Checking version integrity') +runCommand(['pnpm', 'run', 'version:bump', version], 'Bumping version') +runCommand(['pnpm', 'run', 'version:check'], 'Checking version integrity') runCommand( [ @@ -28,9 +35,9 @@ runCommand( 'package.json', 'src-tauri/Cargo.toml', 'src-tauri/Cargo.lock', - 'src-tauri/tauri.conf.json' + 'src-tauri/tauri.conf.json', ], - 'Staging release files' + 'Staging release files', ) runCommand(['git', 'commit', '-m', `chore: release ${versionTag}`], 'Committing changes') diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dd3e896..87f8aa8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aether" -version = "1.1.2" +version = "1.1.3" dependencies = [ "base64 0.22.1", "block2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index dbeac7b..cbe12ba 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "aether" -version = "1.1.2" +version = "1.1.3" description = "Local AI-powered browser and knowledge hub" authors = ["canpixel.com"] edition = "2021" diff --git a/src-tauri/gen/android/buildSrc/src/main/java/com/canur/aether/kotlin/BuildTask.kt b/src-tauri/gen/android/buildSrc/src/main/java/com/canur/aether/kotlin/BuildTask.kt index a7e39eb..f764e2a 100644 --- a/src-tauri/gen/android/buildSrc/src/main/java/com/canur/aether/kotlin/BuildTask.kt +++ b/src-tauri/gen/android/buildSrc/src/main/java/com/canur/aether/kotlin/BuildTask.kt @@ -16,7 +16,7 @@ open class BuildTask : DefaultTask() { @TaskAction fun assemble() { - val executable = """bun"""; + val executable = """pnpm"""; try { runTauriCli(executable) } catch (e: Exception) { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c32c26a..4d4df96 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,12 +2,12 @@ "$schema": "https://schema.tauri.app/config/2", "productName": "ÆTHER", "mainBinaryName": "aether", - "version": "1.1.2", + "version": "1.1.3", "identifier": "com.canur.aether", "build": { - "beforeDevCommand": "bun run dev:vite", + "beforeDevCommand": "pnpm run dev:vite", "devUrl": "http://127.0.0.1:1420", - "beforeBuildCommand": "bun run build:vite", + "beforeBuildCommand": "pnpm run build:vite", "frontendDist": "../dist" }, "app": { @@ -26,26 +26,11 @@ "csp": { "default-src": "'self'", "script-src": "'self'", - "style-src": [ - "'self'", - "'unsafe-inline'" - ], - "img-src": [ - "'self'", - "data:", - "blob:" - ], + "style-src": ["'self'", "'unsafe-inline'"], + "img-src": ["'self'", "data:", "blob:"], "font-src": "'self'", - "connect-src": [ - "'self'", - "ipc:", - "http://ipc.localhost" - ], - "media-src": [ - "'self'", - "data:", - "blob:" - ], + "connect-src": ["'self'", "ipc:", "http://ipc.localhost"], + "media-src": ["'self'", "data:", "blob:"], "object-src": "'none'", "base-uri": "'self'", "form-action": "'none'", @@ -53,20 +38,9 @@ }, "devCsp": { "default-src": "'self'", - "script-src": [ - "'self'", - "'unsafe-inline'", - "'unsafe-eval'" - ], - "style-src": [ - "'self'", - "'unsafe-inline'" - ], - "img-src": [ - "'self'", - "data:", - "blob:" - ], + "script-src": ["'self'", "'unsafe-inline'", "'unsafe-eval'"], + "style-src": ["'self'", "'unsafe-inline'"], + "img-src": ["'self'", "data:", "blob:"], "font-src": "'self'", "connect-src": [ "'self'", @@ -76,11 +50,7 @@ "ws://localhost:1420", "http://127.0.0.1:1420" ], - "media-src": [ - "'self'", - "data:", - "blob:" - ], + "media-src": ["'self'", "data:", "blob:"], "object-src": "'none'", "base-uri": "'self'", "form-action": "'none'" @@ -89,9 +59,7 @@ }, "plugins": { "updater": { - "endpoints": [ - "https://github.com/CanPixel/aether/releases/latest/download/latest.json" - ], + "endpoints": ["https://github.com/CanPixel/aether/releases/latest/download/latest.json"], "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDQ5QzUwQTk2MkJFQjA4MEIKUldRTENPc3JsZ3JGU1FWamQrMkUrb0hmSDR2MktHZjltZVJyb0RCcHQzNFdEelIxNlYzdmlvOFgK", "windows": { "installMode": "passive" @@ -100,14 +68,8 @@ }, "bundle": { "active": true, - "targets": [ - "app" - ], - "icon": [ - "../resources/icon.png", - "../build/icon.icns", - "../build/icon.ico" - ], + "targets": ["app"], + "icon": ["../resources/icon.png", "../build/icon.icns", "../build/icon.ico"], "macOS": { "minimumSystemVersion": "10.15", "dmg": { diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 57c5b27..27aedbd 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -6,7 +6,7 @@ import { useEffect, useMemo, useRef, - useState + useState, } from 'react' import { addPluginListener, invoke, type PluginListener } from '@tauri-apps/api/core' import packageManifest from '../../../package.json' @@ -52,7 +52,7 @@ import { DiagnosticEntry, UpdateCheckResult, UpdateInstallProgress, - UpdateInstallResult + UpdateInstallResult, } from '../../shared/aether' import { BrowserChrome } from './components/BrowserChrome' import { MobileShell } from './components/MobileShell' @@ -82,7 +82,7 @@ import { formatVisibleModelName, getQuickActions, getTabTint, - normalizeComparableUrl + normalizeComparableUrl, } from './utils/aether-ui' import { HAS_NATIVE_TAB_WEBVIEWS, IS_ANDROID, IS_DESKTOP } from './utils/platform' import { useDismissableOverlay } from './utils/dismissable-overlay' @@ -101,7 +101,7 @@ import { SunMoon, Trash2, Waves, - Wind + Wind, /* ZodiacAquarius, SunSnow, @@ -116,7 +116,7 @@ const START_PAGE_URL = 'aether://start' const APPEARANCE_OPTIONS: Array<{ id: Appearance; name: string; description: string }> = [ { id: 'light', name: 'Light', description: 'The pale glass theme.' }, { id: 'system', name: 'System', description: 'Follow the desktop appearance.' }, - { id: 'dark', name: 'Dark', description: 'Deep navy, for night reading.' } + { id: 'dark', name: 'Dark', description: 'Deep navy, for night reading.' }, ] // AiON panel sizing. Must stay in step with --panel-collapsed-width in foundation.css // and PANEL_COLLAPSED_WIDTH in src-tauri/src/lib.rs. @@ -141,7 +141,7 @@ const DASHBOARD_ADDRESSES = new Set([ 'æther://dashboard', 'ice://crystallizer', 'flow://semantic-graph', - 'air://renderer' + 'air://renderer', ]) const SHORTCUT_HELP: Array<{ keys: string; action: string; scope: string }> = [ @@ -152,7 +152,7 @@ const SHORTCUT_HELP: Array<{ keys: string; action: string; scope: string }> = [ { keys: 'Cmd/Ctrl + 2', action: 'Open iCE', scope: 'Global' }, { keys: 'Cmd/Ctrl + 3', action: 'Open Browser', scope: 'Global' }, { keys: 'Cmd/Ctrl + Shift + A', action: 'Toggle AiON', scope: 'Global' }, - { keys: 'Cmd/Ctrl + Shift + C', action: 'Capture current page', scope: 'Browser' } + { keys: 'Cmd/Ctrl + Shift + C', action: 'Capture current page', scope: 'Browser' }, ] function getShortcutFromKeyboardEvent(event: KeyboardEvent): AetherShortcutId | null { @@ -196,16 +196,16 @@ const TEXT_INPUT_TYPES = new Set([ 'search', 'tel', 'text', - 'url' + 'url', ]) function getEditableShortcutTarget( - target: EventTarget | null + target: EventTarget | null, ): HTMLInputElement | HTMLTextAreaElement | HTMLElement | null { if (!(target instanceof HTMLElement)) return null const editable = target.closest( - 'input, textarea, [contenteditable="true"], [contenteditable="plaintext-only"]' + 'input, textarea, [contenteditable="true"], [contenteditable="plaintext-only"]', ) if (!editable) return null if (editable instanceof HTMLInputElement) { @@ -265,7 +265,7 @@ const CLAIM_STOPWORDS = new Set([ 'or', 'by', 'be', - 'but' + 'but', ]) function normalizeAnchorWord(word: string): string { @@ -294,7 +294,7 @@ function minimalCoveringSpan( words: string[], lo: number, hi: number, - weights: Map + weights: Map, ): { start: number; end: number; length: number } | null { const targets = new Set() for (let index = lo; index < hi; index += 1) { @@ -421,7 +421,7 @@ function getErrorMessage(error: unknown): string { function upsertModelProgress( current: ModelDownloadProgress[], - progress: ModelDownloadProgress + progress: ModelDownloadProgress, ): ModelDownloadProgress[] { const index = current.findIndex((item) => item.id === progress.id) if (index === -1) return [...current, progress] @@ -465,11 +465,11 @@ function App(): React.JSX.Element { defaultSearchEngine: 'duckduckgo', aiFreeSearch: true, proxy: { enabled: false, url: 'socks5://127.0.0.1:9050' }, - pinTimezone: false + pinTimezone: false, }, developerMode: false, updates: { autoCheck: true }, - appearance: 'light' + appearance: 'light', }) const [updateCheck, setUpdateCheck] = useState(null) const [updateChecking, setUpdateChecking] = useState(false) @@ -491,7 +491,7 @@ function App(): React.JSX.Element { const [indexStatus, setIndexStatus] = useState(null) const [dashboardOpen, setDashboardOpen] = useState(true) const [workspaceMode, setWorkspaceMode] = useState<'dashboard' | 'crystallizer' | 'flow' | 'air'>( - 'dashboard' + 'dashboard', ) const [activeTabId, setActiveTabId] = useState('') const [selectedCollectionId, setSelectedCollectionId] = useState('') @@ -581,12 +581,12 @@ function App(): React.JSX.Element { // and they tend to be the longest. showToast({ message, tone, durationMs: tone === 'error' ? 7000 : undefined }) }, - [showToast] + [showToast], ) const reportError = useCallback( (error: unknown): void => report(getErrorMessage(error), 'error'), - [report] + [report], ) const reportSuccess = useCallback((message: string): void => report(message, 'success'), [report]) @@ -597,21 +597,21 @@ function App(): React.JSX.Element { const activeTab = useMemo( () => tabs.find((tab) => tab.id === activeTabId) ?? tabs.find((tab) => tab.isActive) ?? tabs[0], - [activeTabId, tabs] + [activeTabId, tabs], ) const activeApp = useMemo(() => apps.find((app) => app.isActive) ?? apps[0], [apps]) const selectedCollection = useMemo( () => collections.find((collection) => collection.id === selectedCollectionId) ?? collections[0], - [collections, selectedCollectionId] + [collections, selectedCollectionId], ) const selectedAirHub = useMemo( () => collections.find((collection) => collection.id === airHubId) ?? selectedCollection, - [airHubId, collections, selectedCollection] + [airHubId, collections, selectedCollection], ) const selectedFlowNode = useMemo( () => flowGraphResult?.nodes.find((node) => node.id === flowSelectedNodeId) ?? null, - [flowGraphResult, flowSelectedNodeId] + [flowGraphResult, flowSelectedNodeId], ) const selectedAirFlowNode = useMemo( () => @@ -621,16 +621,16 @@ function App(): React.JSX.Element { flowGraphResult?.nodes.find((node) => node.kind === 'hub') ?? flowGraphResult?.nodes[0] ?? null, - [airFlowNodeId, flowGraphResult, selectedFlowNode] + [airFlowNodeId, flowGraphResult, selectedFlowNode], ) const askCollection = useMemo( () => collections.find((collection) => collection.id === askCollectionId), - [askCollectionId, collections] + [askCollectionId, collections], ) const usableAskCollections = useMemo( () => collections.filter((collection) => collection.captureCount > 0 && collection.chunkCount > 0), - [collections] + [collections], ) const isStartPage = activeTab?.url === START_PAGE_URL const canUseCurrentPage = Boolean(activeTab?.url) && !isStartPage @@ -649,8 +649,8 @@ function App(): React.JSX.Element { const modelSetupBusy = Boolean( busy === 'Installing local models' || modelDownloadProgress.some( - (progress) => progress.status === 'queued' || progress.status === 'downloading' - ) + (progress) => progress.status === 'queued' || progress.status === 'downloading', + ), ) const modelSetupVisible = modelSetupRequested || (modelSetupNeeded && !modelSetupDismissed) const quickActions = useMemo(() => getQuickActions(activeTab), [activeTab]) @@ -663,7 +663,7 @@ function App(): React.JSX.Element { usableAskCollections.some((collection) => collection.id === selectedCollectionId) ? selectedCollectionId : (usableAskCollections[0]?.id ?? ''), - [usableAskCollections, selectedCollectionId] + [usableAskCollections, selectedCollectionId], ) // What the address bar shows when nobody is typing in it. The draft itself now // lives in BrowserChrome (and MobileShell owns its own input), so this is purely @@ -688,7 +688,7 @@ function App(): React.JSX.Element { const activeTabHubNeedsMetadata = Boolean( activeTabHubShortcut && ((!activeTabHubShortcut.themeColor && activeTab?.themeColor) || - (!activeTabHubShortcut.favicon && activeTab?.favicon)) + (!activeTabHubShortcut.favicon && activeTab?.favicon)), ) const activeSemanticTrailResult = useMemo(() => { if (!semanticTrailResult) return null @@ -728,7 +728,7 @@ function App(): React.JSX.Element { .find(activeTab.id, trimmed, action) .catch((error) => reportError(error)) }, - [activeTab?.id, reportError] + [activeTab?.id, reportError], ) const closeFindBar = useCallback((): void => { @@ -747,8 +747,8 @@ function App(): React.JSX.Element { const captureEntries = await Promise.all( nextCollections.map(async (collection) => [ collection.id, - await window.aether.collections.captures(collection.id) - ]) + await window.aether.collections.captures(collection.id), + ]), ) const nextCapturesByCollection = Object.fromEntries(captureEntries) as Record< string, @@ -769,10 +769,10 @@ function App(): React.JSX.Element { setAskCollectionId((current) => current && nextCollections.some((collection) => collection.id === current) ? current - : nextSelected + : nextSelected, ) }, - [selectedCollectionId] + [selectedCollectionId], ) const refreshShell = useCallback(async (): Promise => { @@ -780,7 +780,7 @@ function App(): React.JSX.Element { window.aether.apps.list(), window.aether.tabs.list(), window.aether.system.status(), - window.aether.system.settings() + window.aether.system.settings(), ]) setApps(nextApps) setTabs(nextTabs) @@ -807,7 +807,7 @@ function App(): React.JSX.Element { refreshCollections(), refreshShortcuts(), refreshSavedIcebergs(), - refreshAirRecent() + refreshAirRecent(), ]) }, [refreshAirRecent, refreshCollections, refreshSavedIcebergs, refreshShell, refreshShortcuts]) @@ -821,13 +821,13 @@ function App(): React.JSX.Element { ...current, updates: { ...current.updates, - lastCheckedAt: result.checkedAt - } + lastCheckedAt: result.checkedAt, + }, })) if (result.updateAvailable) { report( `ÆTHER ${result.latestVersion ?? result.latestName ?? 'update'} is available.`, - 'info' + 'info', ) } else if (!options?.quiet && result.error) { report(result.error, 'error') @@ -840,7 +840,7 @@ function App(): React.JSX.Element { if (!options?.quiet) setUpdateChecking(false) } }, - [report, reportError, reportSuccess] + [report, reportError, reportSuccess], ) const searchLibrary = useCallback( @@ -855,7 +855,7 @@ function App(): React.JSX.Element { setSearching(false) } }, - [reportError] + [reportError], ) const clearSearch = useCallback((): void => setSearchResult(null), []) @@ -901,7 +901,7 @@ function App(): React.JSX.Element { // the ask is not scoped to a hub. const activeThreadCollectionId = useMemo( () => (askCurrentPageOnly ? undefined : askCollectionId || undefined), - [askCollectionId, askCurrentPageOnly] + [askCollectionId, askCurrentPageOnly], ) const clearChatHistory = useCallback((): void => { @@ -946,7 +946,7 @@ function App(): React.JSX.Element { setCapturingLink(false) } }, - [refreshCollections, reportError, reportSuccess] + [refreshCollections, reportError, reportSuccess], ) const captureOpenTabs = useCallback( @@ -971,7 +971,7 @@ function App(): React.JSX.Element { result.failures.length > 0 ? `${saved} Skipped: ${result.failures.map((item) => item.reason).join(' ')}` : saved, - result.failures.length > 0 ? 'info' : 'success' + result.failures.length > 0 ? 'info' : 'success', ) } catch (error) { reportError(error) @@ -979,7 +979,7 @@ function App(): React.JSX.Element { setCapturingLink(false) } }, - [refreshCollections, report, reportBlocked, reportError, tabs] + [refreshCollections, report, reportBlocked, reportError, tabs], ) const refreshDiagnostics = useCallback(async (): Promise => { @@ -1023,7 +1023,7 @@ function App(): React.JSX.Element { reportSuccess( `Exported ${countLabel(result.captureCount, 'source')} (${formatByteSize(result.byteSize)}) to ${ result.path - }` + }`, ) } catch (error) { reportError(error) @@ -1053,7 +1053,7 @@ function App(): React.JSX.Element { result.stillPending > 0 ? `Re-indexed ${result.embedded} passages at ${result.dim} dims — ${result.stillPending} could not be embedded.` : `Re-indexed ${result.embedded} passages at ${result.dim} dims.`, - result.stillPending > 0 ? 'info' : 'success' + result.stillPending > 0 ? 'info' : 'success', ) await refreshIndexStatus() } catch (error) { @@ -1094,7 +1094,7 @@ function App(): React.JSX.Element { return null } }, - [refreshShell, reportError] + [refreshShell, reportError], ) useEffect(() => { @@ -1149,7 +1149,7 @@ function App(): React.JSX.Element { setFindCurrent(result.current) setFindTotal(result.total) }), - [activeTab?.id] + [activeTab?.id], ) useEffect(() => { @@ -1261,7 +1261,7 @@ function App(): React.JSX.Element { showToast({ message, tone: 'info', - durationMs: 0 + durationMs: 0, }) }) @@ -1285,7 +1285,7 @@ function App(): React.JSX.Element { const folder = progress.path?.replace(/[/\\][^/\\]+$/, '') showToast({ message: folder ? `Saved ${progress.filename} to ${folder}` : `Saved ${progress.filename}`, - tone: 'success' + tone: 'success', }) }) @@ -1330,8 +1330,8 @@ function App(): React.JSX.Element { current.includes(model) ? current.filter((item) => item !== model) : [...current, model].sort((first, second) => - first === second ? 0 : first === 'lite' ? -1 : second === 'lite' ? 1 : 0 - ) + first === second ? 0 : first === 'lite' ? -1 : second === 'lite' ? 1 : 0, + ), ) } @@ -1358,7 +1358,7 @@ function App(): React.JSX.Element { async function startModelSetup(): Promise { const modelsToInstall = selectedSetupModels.filter( - (model) => !installedSetupModels.includes(model) + (model) => !installedSetupModels.includes(model), ) if (modelsToInstall.length === 0 && modelSetupCoreInstalled) { setModelSetupError('All selected AiON models are already installed.') @@ -1374,7 +1374,7 @@ function App(): React.JSX.Element { try { const nextStatus = await window.aether.system.downloadModels({ - chatModels: modelsToInstall + chatModels: modelsToInstall, }) setStatus(nextStatus) setModelSetupComplete(true) @@ -1597,13 +1597,13 @@ function App(): React.JSX.Element { id: collectionDialog.collection.id, name: input.name, description: input.description, - icon: input.icon + icon: input.icon, }) await closeCollectionDialog() await refreshCollections(collection.id) setFlowGraphResult(null) reportSuccess(`${collection.name} is ready.`) - } + }, ) } @@ -1694,7 +1694,7 @@ function App(): React.JSX.Element { await runTask('Capturing page', async () => { const result = await window.aether.capture.currentPage({ - collectionId: selectedCollection.id + collectionId: selectedCollection.id, }) setLastCapture(result) await refreshCollections(result.collectionId) @@ -1707,7 +1707,7 @@ function App(): React.JSX.Element { setSemanticTrailResult(null) setFlowGraphResult(null) reportSuccess( - `Saved ${countLabel(result.chunkCount, 'chunk')} into ${result.collectionName}.` + `Saved ${countLabel(result.chunkCount, 'chunk')} into ${result.collectionName}.`, ) }) } @@ -1721,7 +1721,7 @@ function App(): React.JSX.Element { await runTask('Capturing selection', async () => { const result = await window.aether.capture.selection({ - collectionId: selectedCollection.id + collectionId: selectedCollection.id, }) setLastCapture(result) await refreshCollections(result.collectionId) @@ -1729,7 +1729,7 @@ function App(): React.JSX.Element { setSemanticTrailResult(null) setFlowGraphResult(null) reportSuccess( - `Saved ${countLabel(result.provenance?.wordCount ?? 0, 'selected word')} into ${result.collectionName}.` + `Saved ${countLabel(result.provenance?.wordCount ?? 0, 'selected word')} into ${result.collectionName}.`, ) }) } @@ -1762,7 +1762,7 @@ function App(): React.JSX.Element { async function askPrompt( prompt: string, - contextOverride?: { collectionId?: string; includeCurrentPage?: boolean } + contextOverride?: { collectionId?: string; includeCurrentPage?: boolean }, ): Promise { const hasKnowledgeHubs = usableAskCollections.length > 0 const selectedAskCollection = @@ -1805,7 +1805,7 @@ function App(): React.JSX.Element { prompt, collectionId, includeCurrentPage, - requestId + requestId, }) setChatResult(result) @@ -1863,7 +1863,7 @@ function App(): React.JSX.Element { title: activeTab.title || activeTab.host || activeTab.url, url: activeTab.url, favicon: activeTab.favicon, - themeColor: activeTab.themeColor + themeColor: activeTab.themeColor, }) await refreshShortcuts() reportSuccess(updatingPortal ? 'Updated portal appearance.' : 'Saved to Hub.') @@ -1936,7 +1936,7 @@ function App(): React.JSX.Element { try { const result = await window.aether.semanticTrail.generate({ query: trimmedQuery || undefined, - limit: 12 + limit: 12, }) if (semanticTrailRequestRef.current !== requestId) return if ( @@ -1958,13 +1958,13 @@ function App(): React.JSX.Element { } } }, - [canUseCurrentPage, dashboardOpen, reportError, semanticTrailQuery, status?.embeddingModel] + [canUseCurrentPage, dashboardOpen, reportError, semanticTrailQuery, status?.embeddingModel], ) async function buildFlowGraph(query = flowGraphQuery): Promise { await runTask('Mapping Flow', async () => { const result = await window.aether.flow.graph({ - query: query.trim() || undefined + query: query.trim() || undefined, }) setFlowGraphResult(result) const fallbackNodeId = @@ -1973,10 +1973,10 @@ function App(): React.JSX.Element { result.nodes[0]?.id ?? null setFlowSelectedNodeId((current) => - current && result.nodes.some((node) => node.id === current) ? current : fallbackNodeId + current && result.nodes.some((node) => node.id === current) ? current : fallbackNodeId, ) setAirFlowNodeId((current) => - current && result.nodes.some((node) => node.id === current) ? current : null + current && result.nodes.some((node) => node.id === current) ? current : null, ) }) } @@ -2007,7 +2007,7 @@ function App(): React.JSX.Element { airLensKind === 'flow' && flowNode?.kind === 'source' ? flowNode.captureId : undefined, savedIcebergId: airLensKind === 'iceberg' ? activeSavedIceberg?.id : undefined, answer: airLensKind === 'answer' ? (chatResult ?? undefined) : undefined, - limit: 12 + limit: 12, } } @@ -2099,9 +2099,9 @@ function App(): React.JSX.Element { capturedAt: item.capturedAt, chunkIndex: item.chunkIndex, text: item.excerpt, - score: item.score.total + score: item.score.total, }, - item.excerpt + item.excerpt, ) } @@ -2114,7 +2114,7 @@ function App(): React.JSX.Element { reportSuccess( `Mapped ${countLabel(result.items.length, 'topic')} with ${ formatVisibleModelName(result.model) ?? result.model - }.` + }.`, ) return result } catch (error) { @@ -2247,7 +2247,7 @@ function App(): React.JSX.Element { async function updateDefaultSearchEngine(defaultSearchEngine: SearchEngineId): Promise { await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - browser: { defaultSearchEngine } + browser: { defaultSearchEngine }, }) setSettings(nextSettings) // status.aiFreeSearch describes the *selected* engine, so it goes stale the @@ -2261,7 +2261,7 @@ function App(): React.JSX.Element { async function updateAiFreeSearch(aiFreeSearch: boolean): Promise { await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - browser: { aiFreeSearch } + browser: { aiFreeSearch }, }) setSettings(nextSettings) setStatus(await window.aether.system.status()) @@ -2272,7 +2272,7 @@ function App(): React.JSX.Element { async function updateProxyEnabled(enabled: boolean): Promise { await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - browser: { proxy: { enabled } } + browser: { proxy: { enabled } }, }) setSettings(nextSettings) setStatus(await window.aether.system.status()) @@ -2289,7 +2289,7 @@ function App(): React.JSX.Element { } await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - browser: { proxy: { url } } + browser: { proxy: { url } }, }) setSettings(nextSettings) setStatus(await window.aether.system.status()) @@ -2300,7 +2300,7 @@ function App(): React.JSX.Element { async function updatePinTimezone(pinTimezone: boolean): Promise { await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - browser: { pinTimezone } + browser: { pinTimezone }, }) setSettings(nextSettings) setStatus(await window.aether.system.status()) @@ -2329,7 +2329,7 @@ function App(): React.JSX.Element { async function updateAutoCheck(autoCheck: boolean): Promise { await runTask('Updating settings', async () => { const nextSettings = await window.aether.system.updateSettings({ - updates: { autoCheck } + updates: { autoCheck }, }) setSettings(nextSettings) reportSuccess(autoCheck ? 'Update checks enabled.' : 'Update checks disabled.') @@ -2451,7 +2451,7 @@ function App(): React.JSX.Element { showToast({ message: label, tone: 'info', - durationMs: label === 'Capturing page' ? 0 : 2600 + durationMs: label === 'Capturing page' ? 0 : 2600, }) } @@ -2518,7 +2518,7 @@ function App(): React.JSX.Element { // is over every tab). const openTabCount = useMemo( () => tabs.filter((tab) => tab.url && !tab.url.startsWith('aether://')).length, - [tabs] + [tabs], ) // Shared between the desktop and mobile shells so the two trees stay in sync @@ -2701,7 +2701,7 @@ function App(): React.JSX.Element { onCancel: cancelAsk, onChatPromptChange: setChatPrompt, onOpenCitation: openCitation, - onOpenModelSetup: openModelSetup + onOpenModelSetup: openModelSetup, }} backInterceptorRef={mobileBackInterceptorRef} openAionRef={mobileOpenAionRef} @@ -3056,7 +3056,7 @@ function FindBar({ onSearch, onNext, onPrev, - onClose + onClose, }: { inputRef: RefObject query: string @@ -3154,7 +3154,7 @@ function formatSettingsDate(value?: string): string { if (Number.isNaN(date.getTime())) return value return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', - timeStyle: 'short' + timeStyle: 'short', }).format(date) } @@ -3224,7 +3224,7 @@ function SettingsModal({ onOpenUpdateRelease, onAppearanceChange, onUpdateAutoCheck, - onOpenModelSetup + onOpenModelSetup, }: { busy: string | null exportingLibrary: boolean @@ -3266,7 +3266,7 @@ function SettingsModal({ () => { void onClose() }, - !exportingLibrary && !reindexing && !updateInstalling + !exportingLibrary && !reindexing && !updateInstalling, ) const installedVersion = updateCheck?.currentVersion ?? APP_VERSION const releaseNotes = parseReleaseNotes(updateCheck?.releaseNotes) @@ -3275,7 +3275,7 @@ function SettingsModal({ { id: 'bing', name: 'Bing', description: 'Microsoft web search.' }, { id: 'yahoo', name: 'Yahoo!', description: 'Classic portal search.' }, { id: 'ecosia', name: 'Ecosia', description: 'Privacy-aware search that funds trees.' }, - { id: 'duckduckgo', name: 'DuckDuckGo', description: 'Private search by default.' } + { id: 'duckduckgo', name: 'DuckDuckGo', description: 'Private search by default.' }, ] return ( @@ -3303,7 +3303,7 @@ function SettingsModal({ fontWeight: 'bold', marginRight: '-1px', color: 'var(--accent-strong)', - fontSize: '23px' + fontSize: '23px', }} > Æ @@ -3369,8 +3369,8 @@ function SettingsModal({ {describeAiFreeSearch( systemStatus.aiFreeSearch, searchEngines.find( - (engine) => engine.id === settings.browser.defaultSearchEngine - )?.name ?? 'This engine' + (engine) => engine.id === settings.browser.defaultSearchEngine, + )?.name ?? 'This engine', )} @@ -3546,7 +3546,7 @@ function SettingsModal({ {libraryExport ? `Last export: ${countLabel(libraryExport.captureCount, 'source')}, ${formatByteSize( - libraryExport.byteSize + libraryExport.byteSize, )} — ${libraryExport.path}` : 'ÆTHER keeps no cloud copy. Save a snapshot of your hubs, sources, and maps.'} @@ -3700,9 +3700,9 @@ function SettingsModal({ width: `${Math.min( 100, Math.round( - (updateProgress.downloadedBytes / updateProgress.totalBytes) * 100 - ) - )}%` + (updateProgress.downloadedBytes / updateProgress.totalBytes) * 100, + ), + )}%`, } : undefined } @@ -3798,7 +3798,7 @@ function SettingsModal({ {shortcut.keys} {shortcut.action} - ) + ), )} diff --git a/src/renderer/src/components/AirView.tsx b/src/renderer/src/components/AirView.tsx index 4850b7e..74c9fcb 100644 --- a/src/renderer/src/components/AirView.tsx +++ b/src/renderer/src/components/AirView.tsx @@ -9,7 +9,7 @@ import { CollectionSummary, FlowGraphResult, SavedIceberg, - SystemStatus + SystemStatus, } from '../../../shared/aether' import { BookOpen, @@ -21,7 +21,7 @@ import { Search, Sparkles, WandSparkles, - Wind + Wind, } from 'lucide-react' import { countLabel, formatDate, formatVisibleModelName } from '../utils/aether-ui' @@ -62,7 +62,7 @@ const QUICK_LENSES: Array<{ { kind: 'flow', label: 'Flow', icon: Sparkles }, { kind: 'hub', label: 'Hub', icon: BookOpen }, { kind: 'answer', label: 'AiON', icon: WandSparkles }, - { kind: 'iceberg', label: 'iCE', icon: Layers3 } + { kind: 'iceberg', label: 'iCE', icon: Layers3 }, ] export function AirView({ @@ -90,7 +90,7 @@ export function AirView({ onRevealFile, onSelectFlowNode, onSelectHub, - onUseLens + onUseLens, }: AirViewProps): React.JSX.Element { const isBusy = Boolean(busy) const hasPrepared = Boolean(prepared) @@ -101,7 +101,7 @@ export function AirView({ selectedCollection, selectedHub, chatResult, - activeSavedIceberg + activeSavedIceberg, }) async function submit(event: FormEvent): Promise { @@ -190,7 +190,7 @@ export function AirView({ flowGraphResult, selectedCollection, chatResult, - activeSavedIceberg + activeSavedIceberg, }) return ( + , ) }) diff --git a/src/renderer/src/components/loading-ui/TextShimmer.tsx b/src/renderer/src/components/loading-ui/TextShimmer.tsx index 43df856..42d6e6a 100644 --- a/src/renderer/src/components/loading-ui/TextShimmer.tsx +++ b/src/renderer/src/components/loading-ui/TextShimmer.tsx @@ -11,7 +11,7 @@ export function TextShimmer({ children, className, duration = 2.4, - spread = 48 + spread = 48, }: TextShimmerProps) { return ( diff --git a/src/renderer/src/constants/Features.tsx b/src/renderer/src/constants/Features.tsx index ae867f4..0bb757a 100644 --- a/src/renderer/src/constants/Features.tsx +++ b/src/renderer/src/constants/Features.tsx @@ -14,7 +14,7 @@ const stroke = { stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round', - strokeLinejoin: 'round' + strokeLinejoin: 'round', } as const export const portals: Feature = { @@ -29,7 +29,7 @@ export const portals: Feature = { - ) + ), } export const knowledgeHubs: Feature = { @@ -43,7 +43,7 @@ export const knowledgeHubs: Feature = { - ) + ), } export const capture: Feature = { @@ -58,7 +58,7 @@ export const capture: Feature = { - ) + ), } export const aion: Feature = { @@ -73,14 +73,14 @@ export const aion: Feature = { - ) + ), } export const FEATURES: Record = { portals, knowledgeHubs, capture, - aion + aion, } export const FEATURES_ARRAY = Object.values(FEATURES) diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index fb7d57e..44f639d 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -8,5 +8,5 @@ import App from './App' createRoot(document.getElementById('root')!).render( - + , ) diff --git a/src/renderer/src/tauri-aether.ts b/src/renderer/src/tauri-aether.ts index 59fc727..c7834d8 100644 --- a/src/renderer/src/tauri-aether.ts +++ b/src/renderer/src/tauri-aether.ts @@ -43,7 +43,7 @@ import { DiagnosticsExportResult, UpdateCheckResult, UpdateInstallProgress, - UpdateInstallResult + UpdateInstallResult, } from '../../shared/aether' import { IS_ANDROID } from './utils/platform' @@ -60,7 +60,7 @@ if (isTauri) { activate: (appId) => call('aether_apps_activate', { appId }), navigate: (appId, url) => call('aether_apps_navigate', { appId, url }), goBack: (appId) => call('aether_apps_go_back', { appId }), - goForward: (appId) => call('aether_apps_go_forward', { appId }) + goForward: (appId) => call('aether_apps_go_forward', { appId }), }, tabs: { list: () => call('aether_tabs_list'), @@ -75,16 +75,16 @@ if (isTauri) { goForward: (tabId) => call('aether_tabs_go_forward', { tabId }), thumbnail: (tabId) => call('aether_tabs_thumbnail', { tabId }), favicon: (url) => call('aether_browser_favicon', { url }), - clearBrowsingData: () => call('aether_browser_clear_data') + clearBrowsingData: () => call('aether_browser_clear_data'), }, dashboard: { - open: () => call('aether_dashboard_open') + open: () => call('aether_dashboard_open'), }, hub: { list: () => call('aether_hub_list'), create: (input) => call('aether_hub_create', { input }), reorder: (ids) => call('aether_hub_reorder', { ids }), - delete: (id) => call('aether_hub_delete', { id }) + delete: (id) => call('aether_hub_delete', { id }), }, collections: { list: () => call('aether_collections_list'), @@ -93,7 +93,7 @@ if (isTauri) { reorder: (ids) => call('aether_collections_reorder', { ids }), delete: (id) => call('aether_collections_delete', { id }), captures: (collectionId) => - call('aether_collections_captures', { collectionId }) + call('aether_collections_captures', { collectionId }), }, capture: { currentPage: (input) => call('aether_capture_current_page', { input }), @@ -102,17 +102,17 @@ if (isTauri) { urls: (input) => call('aether_capture_urls', { input }), move: (input) => call('aether_capture_move', { input }), delete: (captureId) => call('aether_capture_delete', { captureId }), - suggestHub: () => call('aether_capture_suggest_hub') + suggestHub: () => call('aether_capture_suggest_hub'), }, search: { collection: (input) => call('aether_search_collection', { input }), - library: (input) => call('aether_search_library', { input }) + library: (input) => call('aether_search_library', { input }), }, semanticTrail: { - generate: (input) => call('aether_semantic_trail_generate', { input }) + generate: (input) => call('aether_semantic_trail_generate', { input }), }, flow: { - graph: (input) => call('aether_flow_graph', { input }) + graph: (input) => call('aether_flow_graph', { input }), }, air: { prepare: (input: AirDossierInput) => @@ -120,13 +120,13 @@ if (isTauri) { render: (input: AirDossierInput) => call('aether_air_render', { input }), listRecent: () => call('aether_air_list_recent'), open: (path) => call('aether_air_open', { path }), - reveal: (path) => call('aether_air_reveal', { path }) + reveal: (path) => call('aether_air_reveal', { path }), }, chat: { ask: (input) => call('aether_chat_ask', { input }), cancel: () => call('aether_chat_cancel'), history: (collectionId) => call('aether_chat_history', { collectionId }), - clearHistory: (collectionId) => call('aether_chat_clear_history', { collectionId }) + clearHistory: (collectionId) => call('aether_chat_clear_history', { collectionId }), }, crystallizer: { generate: (input) => call('aether_crystallizer_generate', { input }), @@ -135,7 +135,7 @@ if (isTauri) { save: (input: SaveIcebergInput) => call('aether_crystallizer_save', { input }), reorderSaved: (ids) => call('aether_crystallizer_reorder_saved', { ids }), - deleteSaved: (id) => call('aether_crystallizer_delete_saved', { id }) + deleteSaved: (id) => call('aether_crystallizer_delete_saved', { id }), }, system: { status: () => call('aether_system_status'), @@ -151,7 +151,7 @@ if (isTauri) { indexStatus: () => call('aether_library_index_status'), reindexLibrary: () => call('aether_library_reindex'), openExternalUrl: (url) => call('aether_system_open_external_url', { url }), - downloadModels: (input) => call('aether_system_download_models', { input }) + downloadModels: (input) => call('aether_system_download_models', { input }), }, layout: { setIntelligencePanelCollapsed: (collapsed) => @@ -161,10 +161,10 @@ if (isTauri) { call('aether_layout_show_status_toast', { input }), windowInsets: () => call<{ top: number; bottom: number; left: number; right: number }>( - 'aether_layout_window_insets' + 'aether_layout_window_insets', ), setWebContentBounds: (bounds) => - call('aether_layout_set_web_content_bounds', { ...bounds }) + call('aether_layout_set_web_content_bounds', { ...bounds }), }, events: { onState: (listener: (state: AetherState) => void) => { @@ -179,7 +179,7 @@ if (isTauri) { }, onCaptureProgress: (listener: (progress: CaptureProgress) => void) => { const unlisten = listen('aether:capture-progress', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -188,7 +188,7 @@ if (isTauri) { }, onModelDownloadProgress: (listener: (progress: ModelDownloadProgress) => void) => { const unlisten = listen('aether:model-download-progress', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -197,7 +197,7 @@ if (isTauri) { }, onUpdateProgress: (listener: (progress: UpdateInstallProgress) => void) => { const unlisten = listen('aether:update-progress', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -206,7 +206,7 @@ if (isTauri) { }, onChatStream: (listener: (event: ChatStreamEvent) => void) => { const unlisten = listen('aether:chat-stream', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -215,7 +215,7 @@ if (isTauri) { }, onDownload: (listener: (progress: DownloadProgress) => void) => { const unlisten = listen('aether:download', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -224,7 +224,7 @@ if (isTauri) { }, onShortcut: (listener: (shortcut: AetherShortcutId) => void) => { const unlisten = listen('aether:shortcut', (event) => - listener(event.payload) + listener(event.payload), ) return () => { @@ -240,14 +240,14 @@ if (isTauri) { }, onFindResult: (listener: (result: FindResult) => void) => { const unlisten = listen('aether:find-result', (event) => - listener(event.payload) + listener(event.payload), ) return () => { void unlisten.then((dispose) => dispose()) } - } - } + }, + }, } window.aether = api diff --git a/src/renderer/src/utils/aether-ui.ts b/src/renderer/src/utils/aether-ui.ts index 8e0fe20..3d6a290 100644 --- a/src/renderer/src/utils/aether-ui.ts +++ b/src/renderer/src/utils/aether-ui.ts @@ -7,7 +7,7 @@ import { ProxyStatus, SavedIcebergSummary, TimezonePinStatus, - UpdateInstallProgress + UpdateInstallProgress, } from '../../../shared/aether' import { QuickAction } from '../types/ui' @@ -87,10 +87,10 @@ export function getPortalTint(host: string, themeColor?: string): string { 'github.com': '#6e7681', 'duckduckgo.com': '#de5833', 'ecosia.org': '#39a96b', - 'wikipedia.org': '#727b86' + 'wikipedia.org': '#727b86', } const matchedBrand = Object.entries(brandColors).find( - ([domain]) => normalized === domain || normalized.endsWith(`.${domain}`) + ([domain]) => normalized === domain || normalized.endsWith(`.${domain}`), ) if (matchedBrand) return matchedBrand[1] if (themeColor) return themeColor @@ -180,7 +180,7 @@ function formatLocalModelName(model?: string | null): string | null { } function formatBrandedModelName( model?: string | null, - role: 'chat' | 'embedding' = 'chat' + role: 'chat' | 'embedding' = 'chat', ): string | null { if (!model) return null @@ -233,28 +233,28 @@ const CHAT_MODEL_LADDER: Array<{ id: 'tiny', name: 'AiON TiNY', detail: 'Community build', - matches: (normalized, isCommunity) => normalized.includes('gemma-4-e2b') && isCommunity + matches: (normalized, isCommunity) => normalized.includes('gemma-4-e2b') && isCommunity, }, { id: 'lite', name: 'AiON LiTE', detail: 'Faster, everyday answers', installChoice: 'lite', - matches: (normalized, isCommunity) => normalized.includes('gemma-4-e2b') && !isCommunity + matches: (normalized, isCommunity) => normalized.includes('gemma-4-e2b') && !isCommunity, }, { id: 'wise', name: 'AiON WiSE', detail: 'Deeper synthesis and iCE maps', installChoice: 'wise', - matches: (normalized) => normalized.includes('gemma-4-e4b') + matches: (normalized) => normalized.includes('gemma-4-e4b'), }, { id: 'prime', name: 'AiON PRiME', detail: 'Largest, slowest', - matches: (normalized) => normalized.includes('gemma-4-12b') - } + matches: (normalized) => normalized.includes('gemma-4-12b'), + }, ] function modelMatchesRung(model: string, rung: (typeof CHAT_MODEL_LADDER)[number]): boolean { @@ -286,8 +286,8 @@ export function chatModelRungs(installed: string[]): ChatModelRung[] { name: rung.name, detail: rung.detail, model, - installChoice: rung.installChoice - } + installChoice: rung.installChoice, + }, ] }) @@ -298,7 +298,7 @@ export function chatModelRungs(installed: string[]): ChatModelRung[] { key: model, name: formatBrandedModelName(model, 'chat') ?? model, detail: 'Installed locally', - model + model, })) return [...rungs, ...extras] @@ -306,7 +306,7 @@ export function chatModelRungs(installed: string[]): ChatModelRung[] { export function formatVisibleModelName( model?: string | null, - options: { developerMode?: boolean; role?: 'chat' | 'embedding' } = {} + options: { developerMode?: boolean; role?: 'chat' | 'embedding' } = {}, ): string | null { return options.developerMode ? formatLocalModelName(model) @@ -314,7 +314,7 @@ export function formatVisibleModelName( } export function inferIcebergIcon( - source: Pick & { title?: string; items?: IcebergItem[] } + source: Pick & { title?: string; items?: IcebergItem[] }, ): string { const text = `${source.keyword} ${source.title} ${ source.items?.map((item) => `${item.name} ${item.description}`).join(' ') ?? '' @@ -323,7 +323,7 @@ export function inferIcebergIcon( const matches: Array<[string, RegExp]> = [ [ 'code', - /\b(code|software|programming|developer|javascript|typescript|python|api|github|compiler)\b/ + /\b(code|software|programming|developer|javascript|typescript|python|api|github|compiler)\b/, ], ['cpu', /\b(ai|machine learning|llm|neural|computer|hardware|semiconductor|chip|robotics)\b/], ['brain', /\b(brain|mind|psychology|cognition|learning|intelligence|memory|behavior)\b/], @@ -341,7 +341,7 @@ export function inferIcebergIcon( ['shield', /\b(security|privacy|cryptography|threat|malware|safety|defense)\b/], ['telescope', /\b(space|astronomy|cosmos|planet|star|galaxy|telescope)\b/], ['book', /\b(literature|philosophy|book|education|language|writing|research)\b/], - ['globe', /\b(world|global|culture|geography|travel|internet|web)\b/] + ['globe', /\b(world|global|culture|geography|travel|internet|web)\b/], ] return matches.find(([, pattern]) => pattern.test(text))?.[0] ?? 'snowflake' @@ -357,13 +357,13 @@ export function getQuickActions(activeTab?: BrowserTabSummary): QuickAction[] { { id: 'summarize', label: 'Summarize', - prompt: 'Summarize the current page clearly, using concise sections and local citations.' + prompt: 'Summarize the current page clearly, using concise sections and local citations.', }, { id: 'key-points', label: 'Key points', - prompt: 'Extract the key points from the current page and explain what matters most.' - } + prompt: 'Extract the key points from the current page and explain what matters most.', + }, ] if (activeTab.host.includes('wikipedia.org')) { @@ -373,20 +373,20 @@ export function getQuickActions(activeTab?: BrowserTabSummary): QuickAction[] { id: 'wiki-overview', label: 'Wikipedia overview', prompt: - 'Give me a clean overview of this Wikipedia article, including the topic, why it matters, and the most important sections.' + 'Give me a clean overview of this Wikipedia article, including the topic, why it matters, and the most important sections.', }, { id: 'wiki-timeline', label: 'Timeline', prompt: - 'Create a brief timeline from this Wikipedia article if dates or historical events appear.' + 'Create a brief timeline from this Wikipedia article if dates or historical events appear.', }, { id: 'wiki-related', label: 'Related concepts', prompt: - 'Identify related concepts, people, places, and terms from this Wikipedia article that are worth exploring next.' - } + 'Identify related concepts, people, places, and terms from this Wikipedia article that are worth exploring next.', + }, ] } @@ -397,14 +397,14 @@ export function getQuickActions(activeTab?: BrowserTabSummary): QuickAction[] { id: 'repo-summary', label: 'Repo summary', prompt: - 'Summarize this GitHub page and explain the project purpose, setup, and important files or issues.' + 'Summarize this GitHub page and explain the project purpose, setup, and important files or issues.', }, { id: 'risk-scan', label: 'Risks', prompt: - 'Review this GitHub page for risks, open questions, missing setup details, or maintenance concerns.' - } + 'Review this GitHub page for risks, open questions, missing setup details, or maintenance concerns.', + }, ] } diff --git a/src/renderer/src/utils/collection-icon-data.ts b/src/renderer/src/utils/collection-icon-data.ts index 2782eca..5d9a133 100644 --- a/src/renderer/src/utils/collection-icon-data.ts +++ b/src/renderer/src/utils/collection-icon-data.ts @@ -32,7 +32,7 @@ export const COLLECTION_ICON_OPTIONS: CollectionIconOption[] = [ { id: 'briefcase', label: 'Work', keywords: 'work business client company project' }, { id: 'pin', label: 'Places', keywords: 'pin location travel place map' }, { id: 'star', label: 'Priority', keywords: 'star favorite priority important' }, - { id: 'archive', label: 'Archive', keywords: 'archive files records storage reference' } + { id: 'archive', label: 'Archive', keywords: 'archive files records storage reference' }, ] export function normalizeCollectionIcon(icon?: string): CollectionIconId { diff --git a/src/renderer/src/utils/dismissable-overlay.ts b/src/renderer/src/utils/dismissable-overlay.ts index 6939788..0c676a6 100644 --- a/src/renderer/src/utils/dismissable-overlay.ts +++ b/src/renderer/src/utils/dismissable-overlay.ts @@ -14,7 +14,7 @@ type DismissableOverlay = { // must not be abandoned cannot be dismissed by an errant click or keypress. export function useDismissableOverlay( onDismiss: () => void, - dismissable = true + dismissable = true, ): DismissableOverlay { // A click only counts when the gesture both started and ended on the backdrop. // Selecting text inside the card and releasing outside it fires a click whose target @@ -51,6 +51,6 @@ export function useDismissableOverlay( const dismissed = pressedBackdrop.current && isBackdrop(event) pressedBackdrop.current = false if (dismissed && dismissable) onDismiss() - } + }, } } diff --git a/src/renderer/src/utils/evidence-bundle.test.ts b/src/renderer/src/utils/evidence-bundle.test.ts index c8f63fc..d40abc7 100644 --- a/src/renderer/src/utils/evidence-bundle.test.ts +++ b/src/renderer/src/utils/evidence-bundle.test.ts @@ -1,7 +1,20 @@ -/// -import { describe, expect, test } from 'bun:test' -import { ChatResult } from '../../../shared/aether' -import { buildEvidenceBundle } from './evidence-bundle' +/// +import assert from 'node:assert/strict' +import { describe, test } from 'node:test' +import type { ChatResult } from '../../../shared/aether' +// Node's ESM resolver needs the real extension; there is no bundler in the loop +// when these run under `node --test`. +import { buildEvidenceBundle } from './evidence-bundle.ts' + +// node:assert has no `expect(...).toContain(...)`. Asserting on `.includes()` +// alone would report a bare "expected true to be true", so carry the needle and +// the full output into the failure message. +const contains = (haystack: string, needle: string): void => { + assert.ok( + haystack.includes(needle), + `expected output to contain ${JSON.stringify(needle)}\n--- actual output ---\n${haystack}`, + ) +} const result: ChatResult = { answer: 'The finding is supported by the captured passage [1].', @@ -17,31 +30,31 @@ const result: ChatResult = { capturedAt: '2026-08-02T10:00:00Z', chunkIndex: 2, text: 'Exact retrieved text.\nSecond line.', - score: 0.92 - } + score: 0.92, + }, ], metrics: { generatedTokens: 14, tokensPerSecond: 8, elapsedSeconds: 2, - chunks: 1 - } + chunks: 1, + }, } describe('buildEvidenceBundle', () => { test('preserves claim markers and includes exact passage provenance', () => { const bundle = buildEvidenceBundle(result) - expect(bundle).toContain('captured passage [1]') - expect(bundle).toContain('### [1] Research Article') - expect(bundle).toContain('> Exact retrieved text.\n> Second line.') - expect(bundle).toContain('Capture ID: capture-1') - expect(bundle).toContain('Passage: chunk 3') - expect(bundle).toContain('Generated locally with local-model.') + contains(bundle, 'captured passage [1]') + contains(bundle, '### [1] Research Article') + contains(bundle, '> Exact retrieved text.\n> Second line.') + contains(bundle, 'Capture ID: capture-1') + contains(bundle, 'Passage: chunk 3') + contains(bundle, 'Generated locally with local-model.') }) test('states when an answer has no evidence', () => { const bundle = buildEvidenceBundle({ ...result, citations: [] }) - expect(bundle).toContain('No retrieved passages were attached to this answer.') + contains(bundle, 'No retrieved passages were attached to this answer.') }) }) diff --git a/src/renderer/src/utils/evidence-bundle.ts b/src/renderer/src/utils/evidence-bundle.ts index e6d9638..65c5435 100644 --- a/src/renderer/src/utils/evidence-bundle.ts +++ b/src/renderer/src/utils/evidence-bundle.ts @@ -1,4 +1,4 @@ -import { ChatResult } from '../../../shared/aether' +import type { ChatResult } from '../../../shared/aether' function quoteMarkdown(text: string): string { return text @@ -27,7 +27,7 @@ export function buildEvidenceBundle(result: ChatResult): string { `Source: ${citation.url}`, `Captured: ${citation.capturedAt}`, `Capture ID: ${citation.captureId}`, - `Passage: chunk ${citation.chunkIndex + 1}` + `Passage: chunk ${citation.chunkIndex + 1}`, ) }) } else { diff --git a/src/renderer/src/utils/extraction-receipt.test.ts b/src/renderer/src/utils/extraction-receipt.test.ts index 506301b..388d850 100644 --- a/src/renderer/src/utils/extraction-receipt.test.ts +++ b/src/renderer/src/utils/extraction-receipt.test.ts @@ -1,7 +1,20 @@ -/// -import { expect, test } from 'bun:test' -import { CaptureSummary } from '../../../shared/aether' -import { buildExtractionReceipt } from './extraction-receipt' +/// +import assert from 'node:assert/strict' +import { test } from 'node:test' +import type { CaptureSummary } from '../../../shared/aether' +// Node's ESM resolver needs the real extension; there is no bundler in the loop +// when these run under `node --test`. +import { buildExtractionReceipt } from './extraction-receipt.ts' + +// node:assert has no `expect(...).toContain(...)`. Asserting on `.includes()` +// alone would report a bare "expected true to be true", so carry the needle and +// the full output into the failure message. +const contains = (haystack: string, needle: string): void => { + assert.ok( + haystack.includes(needle), + `expected output to contain ${JSON.stringify(needle)}\n--- actual output ---\n${haystack}`, + ) +} test('serializes the complete persistent extraction receipt', () => { const capture: CaptureSummary = { @@ -26,14 +39,14 @@ test('serializes the complete persistent extraction receipt', () => { contentScope: 'page', contentSelector: 'article', wordCount: 320, - fallbackReason: 'Live DOM unavailable.' - } + fallbackReason: 'Live DOM unavailable.', + }, } const receipt = buildExtractionReceipt(capture) - expect(receipt).toContain('Receipt version: 1') - expect(receipt).toContain('Requested URL: https://example.com/start') - expect(receipt).toContain('Canonical URL: https://example.com/article') - expect(receipt).toContain('SHA-256: abc123') - expect(receipt).toContain('Fallback: Live DOM unavailable.') + contains(receipt, 'Receipt version: 1') + contains(receipt, 'Requested URL: https://example.com/start') + contains(receipt, 'Canonical URL: https://example.com/article') + contains(receipt, 'SHA-256: abc123') + contains(receipt, 'Fallback: Live DOM unavailable.') }) diff --git a/src/renderer/src/utils/extraction-receipt.ts b/src/renderer/src/utils/extraction-receipt.ts index 78d8b9d..fe87bc1 100644 --- a/src/renderer/src/utils/extraction-receipt.ts +++ b/src/renderer/src/utils/extraction-receipt.ts @@ -1,4 +1,4 @@ -import { CaptureSummary } from '../../../shared/aether' +import type { CaptureSummary } from '../../../shared/aether' export function buildExtractionReceipt(capture: CaptureSummary): string { const provenance = capture.provenance @@ -7,7 +7,7 @@ export function buildExtractionReceipt(capture: CaptureSummary): string { '# AETHER extraction receipt', `Captured: ${capture.capturedAt}`, `Source: ${capture.url}`, - 'Receipt: legacy capture without extraction provenance' + 'Receipt: legacy capture without extraction provenance', ].join('\n') } @@ -17,7 +17,7 @@ export function buildExtractionReceipt(capture: CaptureSummary): string { `Extractor: ${provenance.extractorVersion || 'legacy extractor'}`, `Captured: ${capture.capturedAt}`, `Record: immutable ${provenance.contentScope}`, - `Source: ${capture.url}` + `Source: ${capture.url}`, ] if (provenance.requestedUrl && provenance.requestedUrl !== capture.url) { lines.push(`Requested URL: ${provenance.requestedUrl}`) @@ -27,7 +27,7 @@ export function buildExtractionReceipt(capture: CaptureSummary): string { `Method: ${provenance.extractionMethod}`, `Selector: ${provenance.contentSelector || 'legacy extractor'}`, `Words: ${provenance.wordCount}`, - `SHA-256: ${provenance.contentHash}` + `SHA-256: ${provenance.contentHash}`, ) if (provenance.author) lines.push(`Author: ${provenance.author}`) if (provenance.publishedAt) lines.push(`Published: ${provenance.publishedAt}`) diff --git a/src/renderer/src/utils/site-favicon.ts b/src/renderer/src/utils/site-favicon.ts index e30c55a..2249c7a 100644 --- a/src/renderer/src/utils/site-favicon.ts +++ b/src/renderer/src/utils/site-favicon.ts @@ -35,7 +35,7 @@ function resolveFavicon(api: AetherApi, iconUrl: string): Promise */ export function useSiteFavicon(iconUrl?: string): string | undefined { const [dataUri, setDataUri] = useState(() => - iconUrl ? (resolved.get(iconUrl) ?? undefined) : undefined + iconUrl ? (resolved.get(iconUrl) ?? undefined) : undefined, ) useEffect(() => { diff --git a/src/renderer/src/utils/web-content-bounds.ts b/src/renderer/src/utils/web-content-bounds.ts index 19a35d1..7c11557 100644 --- a/src/renderer/src/utils/web-content-bounds.ts +++ b/src/renderer/src/utils/web-content-bounds.ts @@ -10,7 +10,7 @@ import { useLayoutEffect, type RefObject } from 'react' // covered by a live page. export function useWebContentBounds( ref: RefObject, - deps: unknown[] = [] + deps: unknown[] = [], ): void { useLayoutEffect(() => { const host = ref.current @@ -37,7 +37,7 @@ export function useWebContentBounds( top, left: rect.left, width: rect.width, - height + height, }) .catch(() => undefined) } diff --git a/tools/dmg-metadata/index.mjs b/tools/dmg-metadata/index.mjs new file mode 100755 index 0000000..3cf6744 --- /dev/null +++ b/tools/dmg-metadata/index.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env node + +import console from 'node:console' +import { readFileSync } from 'node:fs' +import path from 'node:path' +import process from 'node:process' +import DSStore from 'ds-store' + +const config = JSON.parse( + readFileSync(path.join(process.cwd(), 'src-tauri', 'tauri.conf.json'), 'utf8'), +) + +const mountPath = process.argv[2] +if (!mountPath) { + console.error('Usage: aether-dmg-metadata ') + process.exit(2) +} + +const dmg = config.bundle.macOS.dmg +const store = new DSStore() + +store.vSrn(1) +store.setIconSize(128) +store.setBackgroundColor(239 / 255, 251 / 255, 1) +store.setBackgroundPath(path.join(mountPath, '.background', 'dmg-background.tiff')) +store.setWindowSize(dmg.windowSize.width, dmg.windowSize.height) +store.setIconPos(`${config.productName}.app`, dmg.appPosition.x, dmg.appPosition.y) +store.setIconPos('Applications', dmg.applicationFolderPosition.x, dmg.applicationFolderPosition.y) + +await new Promise((resolve, reject) => { + store.write(path.join(mountPath, '.DS_Store'), (error) => { + if (error) reject(error) + else resolve() + }) +}) diff --git a/tools/dmg-metadata/package.json b/tools/dmg-metadata/package.json new file mode 100644 index 0000000..0c8f0c4 --- /dev/null +++ b/tools/dmg-metadata/package.json @@ -0,0 +1,16 @@ +{ + "name": "@aether/dmg-metadata", + "version": "1.0.0", + "private": true, + "description": "macOS-only Finder metadata writer for the ÆTHER DMG", + "type": "module", + "os": [ + "darwin" + ], + "bin": { + "aether-dmg-metadata": "index.mjs" + }, + "dependencies": { + "ds-store": "0.1.6" + } +} diff --git a/tsconfig.json b/tsconfig.json index 3ba65ea..9e2362a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,4 @@ { "files": [], - "references": [{ "path": "./tsconfig.web.json" }], - "compilerOptions": { - "types": ["bun"] - } + "references": [{ "path": "./tsconfig.web.json" }] } diff --git a/tsconfig.web.json b/tsconfig.web.json index 71d7073..851abb9 100644 --- a/tsconfig.web.json +++ b/tsconfig.web.json @@ -16,6 +16,9 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, + // *.test.ts import the module under test with an explicit .ts extension so + // `node --test` can resolve it without a bundler. Permits, does not require. + "allowImportingTsExtensions": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true, "noUnusedLocals": true, diff --git a/vite.config.ts b/vite.config.ts index e0ab0fe..334921b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -11,16 +11,16 @@ export default defineConfig({ // loads from; the server must bind there (or 0.0.0.0) to be reachable. host: process.env.TAURI_DEV_HOST || '127.0.0.1', port: 1420, - strictPort: true + strictPort: true, }, build: { outDir: resolve('dist'), - emptyOutDir: true + emptyOutDir: true, }, resolve: { alias: { - '@renderer': resolve('src/renderer/src') - } + '@renderer': resolve('src/renderer/src'), + }, }, - plugins: [react()] + plugins: [react()], })