diff --git a/cmd/bugseti/.gitignore b/cmd/bugseti/.gitignore deleted file mode 100644 index 94f214e3..00000000 --- a/cmd/bugseti/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Build output -bin/ -frontend/dist/ -frontend/node_modules/ -frontend/.angular/ - -# IDE -.idea/ -.vscode/ -*.swp -*.swo -*~ - -# OS -.DS_Store -Thumbs.db - -# Go -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test -*.test -*.out -coverage/ - -# Wails -wails.json diff --git a/cmd/bugseti/README.md b/cmd/bugseti/README.md deleted file mode 100644 index 3739b5c5..00000000 --- a/cmd/bugseti/README.md +++ /dev/null @@ -1,186 +0,0 @@ -# BugSETI - -**Distributed Bug Fixing - like SETI@home but for code** - -BugSETI is a system tray application that helps developers contribute to open source by fixing bugs in their spare CPU cycles. It fetches issues from GitHub repositories, prepares context using AI, and guides you through the fix-and-submit workflow. - -## Features - -- **System Tray Integration**: Runs quietly in the background, ready when you are -- **Issue Queue**: Automatically fetches and queues issues from configured repositories -- **AI Context Seeding**: Prepares relevant code context for each issue using pattern matching -- **Workbench UI**: Full-featured interface for reviewing issues and submitting fixes -- **Automated PR Submission**: Streamlined workflow from fix to pull request -- **Stats & Leaderboard**: Track your contributions and compete with the community - -## Installation - -### From Source - -```bash -# Clone the repository -git clone https://forge.lthn.ai/core/go.git -cd core - -# Build BugSETI -task bugseti:build - -# The binary will be in build/bin/bugseti -``` - -### Prerequisites - -- Go 1.25 or later -- Node.js 18+ and npm (for frontend) -- GitHub CLI (`gh`) authenticated -- Chrome/Chromium (optional, for webview features) - -## Configuration - -On first launch, BugSETI will show an onboarding wizard to configure: - -1. **GitHub Token**: For fetching issues and submitting PRs -2. **Repositories**: Which repos to fetch issues from -3. **Filters**: Issue labels, difficulty levels, languages -4. **Notifications**: How to alert you about new issues - -### Configuration File - -Settings are stored in `~/.config/bugseti/config.json`: - -```json -{ - "github_token": "ghp_...", - "repositories": [ - "host-uk/core", - "example/repo" - ], - "filters": { - "labels": ["good first issue", "help wanted", "bug"], - "languages": ["go", "typescript"], - "max_age_days": 30 - }, - "notifications": { - "enabled": true, - "sound": true - }, - "fetch_interval_minutes": 30 -} -``` - -## Usage - -### Starting BugSETI - -```bash -# Run the application -./bugseti - -# Or use task runner -task bugseti:run -``` - -The app will appear in your system tray. Click the icon to see the quick menu or open the workbench. - -### Workflow - -1. **Browse Issues**: Click the tray icon to see available issues -2. **Select an Issue**: Choose one to work on from the queue -3. **Review Context**: BugSETI shows relevant files and patterns -4. **Fix the Bug**: Make your changes in your preferred editor -5. **Submit PR**: Use the workbench to create and submit your pull request - -### Keyboard Shortcuts - -| Shortcut | Action | -|----------|--------| -| `Ctrl+Shift+B` | Open workbench | -| `Ctrl+Shift+N` | Next issue | -| `Ctrl+Shift+S` | Submit PR | - -## Architecture - -``` -cmd/bugseti/ - main.go # Application entry point - tray.go # System tray service - icons/ # Tray icons (light/dark/template) - frontend/ # Angular frontend - src/ - app/ - tray/ # Tray panel component - workbench/ # Main workbench - settings/ # Settings panel - onboarding/ # First-run wizard - -internal/bugseti/ - config.go # Configuration service - fetcher.go # GitHub issue fetcher - queue.go # Issue queue management - seeder.go # Context seeding via AI - submit.go # PR submission - notify.go # Notification service - stats.go # Statistics tracking -``` - -## Contributing - -We welcome contributions! Here's how to get involved: - -### Development Setup - -```bash -# Install dependencies -cd cmd/bugseti/frontend -npm install - -# Run in development mode -task bugseti:dev -``` - -### Running Tests - -```bash -# Go tests -go test ./cmd/bugseti/... ./internal/bugseti/... - -# Frontend tests -cd cmd/bugseti/frontend -npm test -``` - -### Submitting Changes - -1. Fork the repository -2. Create a feature branch: `git checkout -b feature/my-feature` -3. Make your changes and add tests -4. Run the test suite: `task test` -5. Submit a pull request - -### Code Style - -- Go: Follow standard Go conventions, run `go fmt` -- TypeScript/Angular: Follow Angular style guide -- Commits: Use conventional commit messages - -## Roadmap - -- [ ] Auto-update mechanism -- [ ] Team/organization support -- [ ] Integration with more issue trackers (GitLab, Jira) -- [ ] AI-assisted code review -- [ ] Mobile companion app - -## License - -MIT License - see [LICENSE](../../LICENSE) for details. - -## Acknowledgments - -- Inspired by SETI@home and distributed computing projects -- Built with [Wails v3](https://wails.io/) for native desktop integration -- Uses [Angular](https://angular.io/) for the frontend - ---- - -**Happy Bug Hunting!** diff --git a/cmd/bugseti/Taskfile.yml b/cmd/bugseti/Taskfile.yml deleted file mode 100644 index b19deeff..00000000 --- a/cmd/bugseti/Taskfile.yml +++ /dev/null @@ -1,134 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "bugseti" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9246}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - - build:all: - summary: Builds for all platforms - cmds: - - task: darwin:build - vars: - PRODUCTION: "true" - - task: linux:build - vars: - PRODUCTION: "true" - - task: windows:build - vars: - PRODUCTION: "true" - - package:all: - summary: Packages for all platforms - cmds: - - task: darwin:package - - task: linux:package - - task: windows:package - - clean: - summary: Cleans build artifacts - cmds: - - rm -rf bin/ - - rm -rf frontend/dist/ - - rm -rf frontend/node_modules/ - - # Release targets - release:stable: - summary: Creates a stable release tag - desc: | - Creates a stable release tag (bugseti-vX.Y.Z). - Usage: task release:stable VERSION=1.0.0 - preconditions: - - sh: '[ -n "{{.VERSION}}" ]' - msg: "VERSION is required. Usage: task release:stable VERSION=1.0.0" - cmds: - - git tag -a "bugseti-v{{.VERSION}}" -m "BugSETI v{{.VERSION}} stable release" - - echo "Created tag bugseti-v{{.VERSION}}" - - echo "To push: git push origin bugseti-v{{.VERSION}}" - - release:beta: - summary: Creates a beta release tag - desc: | - Creates a beta release tag (bugseti-vX.Y.Z-beta.N). - Usage: task release:beta VERSION=1.0.0 BETA=1 - preconditions: - - sh: '[ -n "{{.VERSION}}" ]' - msg: "VERSION is required. Usage: task release:beta VERSION=1.0.0 BETA=1" - - sh: '[ -n "{{.BETA}}" ]' - msg: "BETA number is required. Usage: task release:beta VERSION=1.0.0 BETA=1" - cmds: - - git tag -a "bugseti-v{{.VERSION}}-beta.{{.BETA}}" -m "BugSETI v{{.VERSION}} beta {{.BETA}}" - - echo "Created tag bugseti-v{{.VERSION}}-beta.{{.BETA}}" - - echo "To push: git push origin bugseti-v{{.VERSION}}-beta.{{.BETA}}" - - release:nightly: - summary: Creates a nightly release tag - desc: Creates a nightly release tag (bugseti-nightly-YYYYMMDD) - vars: - DATE: - sh: date -u +%Y%m%d - cmds: - - git tag -a "bugseti-nightly-{{.DATE}}" -m "BugSETI nightly build {{.DATE}}" - - echo "Created tag bugseti-nightly-{{.DATE}}" - - echo "To push: git push origin bugseti-nightly-{{.DATE}}" - - release:push: - summary: Pushes the latest release tag - desc: | - Pushes the most recent bugseti-* tag to origin. - Usage: task release:push - vars: - TAG: - sh: git tag -l 'bugseti-*' | sort -V | tail -1 - preconditions: - - sh: '[ -n "{{.TAG}}" ]' - msg: "No bugseti-* tags found" - cmds: - - echo "Pushing tag {{.TAG}}..." - - git push origin {{.TAG}} - - echo "Tag {{.TAG}} pushed. GitHub Actions will build and release." - - release:list: - summary: Lists all BugSETI release tags - cmds: - - echo "=== BugSETI Release Tags ===" - - git tag -l 'bugseti-*' | sort -V - - version: - summary: Shows current version info - cmds: - - | - echo "=== BugSETI Version Info ===" - echo "Latest stable tag:" - git tag -l 'bugseti-v*' | grep -v beta | sort -V | tail -1 || echo " (none)" - echo "Latest beta tag:" - git tag -l 'bugseti-v*-beta.*' | sort -V | tail -1 || echo " (none)" - echo "Latest nightly tag:" - git tag -l 'bugseti-nightly-*' | sort -V | tail -1 || echo " (none)" diff --git a/cmd/bugseti/build/Taskfile.yml b/cmd/bugseti/build/Taskfile.yml deleted file mode 100644 index 96e71339..00000000 --- a/cmd/bugseti/build/Taskfile.yml +++ /dev/null @@ -1,90 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=false -ts -i - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} - vars: - VITE_PORT: '{{.VITE_PORT | default "5173"}}' - - update:build-assets: - summary: Updates the build assets - dir: build - preconditions: - - sh: '[ -n "{{.APP_NAME}}" ]' - msg: "APP_NAME variable is required" - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/cmd/bugseti/build/config.yml b/cmd/bugseti/build/config.yml deleted file mode 100644 index b55fb12e..00000000 --- a/cmd/bugseti/build/config.yml +++ /dev/null @@ -1,38 +0,0 @@ -# BugSETI Wails v3 Build Configuration -version: '3' - -# Build metadata -info: - companyName: "Lethean" - productName: "BugSETI" - productIdentifier: "io.lethean.bugseti" - description: "Distributed Bug Fixing - like SETI@home but for code" - copyright: "Copyright 2026 Lethean" - comments: "Distributed OSS bug fixing application" - version: "0.1.0" - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: go build -buildvcs=false -gcflags=all=-l -o bin/bugseti . - type: blocking - - cmd: cd frontend && npx ng serve --port ${WAILS_FRONTEND_PORT:-9246} - type: background - - cmd: bin/bugseti - type: primary diff --git a/cmd/bugseti/build/darwin/Info.dev.plist b/cmd/bugseti/build/darwin/Info.dev.plist deleted file mode 100644 index af4bd2c0..00000000 --- a/cmd/bugseti/build/darwin/Info.dev.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - CFBundlePackageType - APPL - CFBundleName - BugSETI (Dev) - CFBundleExecutable - bugseti - CFBundleIdentifier - io.lethean.bugseti.dev - CFBundleVersion - 0.1.0-dev - CFBundleGetInfoString - Distributed Bug Fixing - like SETI@home but for code (Development) - CFBundleShortVersionString - 0.1.0-dev - CFBundleIconFile - icons.icns - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - - LSUIElement - - LSApplicationCategoryType - public.app-category.developer-tools - NSAppTransportSecurity - - NSAllowsLocalNetworking - - NSAllowsArbitraryLoads - - - - diff --git a/cmd/bugseti/build/darwin/Info.plist b/cmd/bugseti/build/darwin/Info.plist deleted file mode 100644 index 061b7b48..00000000 --- a/cmd/bugseti/build/darwin/Info.plist +++ /dev/null @@ -1,35 +0,0 @@ - - - - - CFBundlePackageType - APPL - CFBundleName - BugSETI - CFBundleExecutable - bugseti - CFBundleIdentifier - io.lethean.bugseti - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - Distributed Bug Fixing - like SETI@home but for code - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons.icns - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - - LSUIElement - - LSApplicationCategoryType - public.app-category.developer-tools - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - diff --git a/cmd/bugseti/build/darwin/Taskfile.yml b/cmd/bugseti/build/darwin/Taskfile.yml deleted file mode 100644 index bf49fbe9..00000000 --- a/cmd/bugseti/build/darwin/Taskfile.yml +++ /dev/null @@ -1,84 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - PRODUCTION: '{{.PRODUCTION | default "true"}}' - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - PRODUCTION: '{{.PRODUCTION | default "true"}}' - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - deps: - - task: build - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/cmd/bugseti/build/linux/Taskfile.yml b/cmd/bugseti/build/linux/Taskfile.yml deleted file mode 100644 index 7fd20f73..00000000 --- a/cmd/bugseti/build/linux/Taskfile.yml +++ /dev/null @@ -1,103 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png {{.APP_NAME}}.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '{{.APP_NAME}}.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: 'BugSETI' - EXEC: '{{.APP_NAME}}' - ICON: 'bugseti' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/cmd/bugseti/build/linux/nfpm/nfpm.yaml b/cmd/bugseti/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 23acab04..00000000 --- a/cmd/bugseti/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,34 +0,0 @@ -# nfpm configuration for BugSETI -name: "bugseti" -arch: "${GOARCH}" -platform: "linux" -version: "0.1.0" -section: "devel" -priority: "optional" -maintainer: "Lethean " -description: | - BugSETI - Distributed Bug Fixing - Like SETI@home but for code. Install the system tray app, - it pulls OSS issues from GitHub, AI prepares context, - you fix bugs, and it auto-submits PRs. -vendor: "Lethean" -homepage: "https://forge.lthn.ai/core/go" -license: "MIT" - -contents: - - src: ./bin/bugseti - dst: /usr/bin/bugseti - - src: ./build/linux/bugseti.desktop - dst: /usr/share/applications/bugseti.desktop - - src: ./build/appicon.png - dst: /usr/share/icons/hicolor/256x256/apps/bugseti.png - -overrides: - deb: - dependencies: - - libwebkit2gtk-4.1-0 - - libgtk-3-0 - rpm: - dependencies: - - webkit2gtk4.1 - - gtk3 diff --git a/cmd/bugseti/build/windows/Taskfile.yml b/cmd/bugseti/build/windows/Taskfile.yml deleted file mode 100644 index ac1d2d91..00000000 --- a/cmd/bugseti/build/windows/Taskfile.yml +++ /dev/null @@ -1,49 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Windows - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:nsis - - create:nsis: - summary: Creates an NSIS installer - cmds: - - wails3 tool package -name {{.APP_NAME}} -format nsis -config ./build/windows/nsis/installer.nsi -out {{.ROOT_DIR}}/bin - - create:msi: - summary: Creates an MSI installer - cmds: - - wails3 tool package -name {{.APP_NAME}} -format msi -config ./build/windows/wix/main.wxs -out {{.ROOT_DIR}}/bin - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/cmd/bugseti/frontend/angular.json b/cmd/bugseti/frontend/angular.json deleted file mode 100644 index 97d1fe6a..00000000 --- a/cmd/bugseti/frontend/angular.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "bugseti": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss", - "standalone": true - } - }, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/bugseti", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "tsconfig.app.json", - "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "bugseti:build:production" - }, - "development": { - "buildTarget": "bugseti:build:development" - } - }, - "defaultConfiguration": "development" - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": ["zone.js", "zone.js/testing"], - "tsConfig": "tsconfig.spec.json", - "inlineStyleLanguage": "scss", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [] - } - } - } - } - }, - "cli": { - "analytics": false - } -} diff --git a/cmd/bugseti/frontend/package-lock.json b/cmd/bugseti/frontend/package-lock.json deleted file mode 100644 index 0904b6fa..00000000 --- a/cmd/bugseti/frontend/package-lock.json +++ /dev/null @@ -1,15012 +0,0 @@ -{ - "name": "bugseti", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "bugseti", - "version": "0.1.0", - "dependencies": { - "@angular/animations": "^19.1.0", - "@angular/common": "^19.1.0", - "@angular/compiler": "^19.1.0", - "@angular/core": "^19.1.0", - "@angular/forms": "^19.1.0", - "@angular/platform-browser": "^19.1.0", - "@angular/platform-browser-dynamic": "^19.1.0", - "@angular/router": "^19.1.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.1.0", - "@angular/cli": "^21.1.2", - "@angular/compiler-cli": "^19.1.0", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.5.2" - } - }, - "node_modules/@algolia/abtesting": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.12.2.tgz", - "integrity": "sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-abtesting": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz", - "integrity": "sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-analytics": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.46.2.tgz", - "integrity": "sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-common": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", - "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-insights": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.46.2.tgz", - "integrity": "sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-personalization": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.46.2.tgz", - "integrity": "sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-query-suggestions": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz", - "integrity": "sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/client-search": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.46.2.tgz", - "integrity": "sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/ingestion": { - "version": "1.46.2", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.46.2.tgz", - "integrity": "sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/monitoring": { - "version": "1.46.2", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.46.2.tgz", - "integrity": "sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/recommend": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.46.2.tgz", - "integrity": "sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-browser-xhr": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", - "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-fetch": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", - "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@algolia/requester-node-http": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", - "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/client-common": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular-devkit/architect": { - "version": "0.1902.19", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1902.19.tgz", - "integrity": "sha512-iexYDIYpGAeAU7T60bGcfrGwtq1bxpZixYxWuHYiaD1b5baQgNSfd1isGEOh37GgDNsf4In9i2LOLPm0wBdtgQ==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "19.2.19", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/architect/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@angular-devkit/build-angular": { - "version": "19.2.19", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.2.19.tgz", - "integrity": "sha512-uIxi6Vzss6+ycljVhkyPUPWa20w8qxJL9lEn0h6+sX/fhM8Djt0FHIuTQjoX58EoMaQ/1jrXaRaGimkbaFcG9A==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1902.19", - "@angular-devkit/build-webpack": "0.1902.19", - "@angular-devkit/core": "19.2.19", - "@angular/build": "19.2.19", - "@babel/core": "7.26.10", - "@babel/generator": "7.26.10", - "@babel/helper-annotate-as-pure": "7.25.9", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.26.8", - "@babel/plugin-transform-async-to-generator": "7.25.9", - "@babel/plugin-transform-runtime": "7.26.10", - "@babel/preset-env": "7.26.9", - "@babel/runtime": "7.26.10", - "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "19.2.19", - "@vitejs/plugin-basic-ssl": "1.2.0", - "ansi-colors": "4.1.3", - "autoprefixer": "10.4.20", - "babel-loader": "9.2.1", - "browserslist": "^4.21.5", - "copy-webpack-plugin": "12.0.2", - "css-loader": "7.1.2", - "esbuild-wasm": "0.25.4", - "fast-glob": "3.3.3", - "http-proxy-middleware": "3.0.5", - "istanbul-lib-instrument": "6.0.3", - "jsonc-parser": "3.3.1", - "karma-source-map-support": "1.4.0", - "less": "4.2.2", - "less-loader": "12.2.0", - "license-webpack-plugin": "4.0.2", - "loader-utils": "3.3.1", - "mini-css-extract-plugin": "2.9.2", - "open": "10.1.0", - "ora": "5.4.1", - "picomatch": "4.0.2", - "piscina": "4.8.0", - "postcss": "8.5.2", - "postcss-loader": "8.1.1", - "resolve-url-loader": "5.0.0", - "rxjs": "7.8.1", - "sass": "1.85.0", - "sass-loader": "16.0.5", - "semver": "7.7.1", - "source-map-loader": "5.0.0", - "source-map-support": "0.5.21", - "terser": "5.39.0", - "tree-kill": "1.2.2", - "tslib": "2.8.1", - "webpack": "5.98.0", - "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.2.2", - "webpack-merge": "6.0.1", - "webpack-subresource-integrity": "5.1.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "optionalDependencies": { - "esbuild": "0.25.4" - }, - "peerDependencies": { - "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", - "@angular/localize": "^19.0.0 || ^19.2.0-next.0", - "@angular/platform-server": "^19.0.0 || ^19.2.0-next.0", - "@angular/service-worker": "^19.0.0 || ^19.2.0-next.0", - "@angular/ssr": "^19.2.19", - "@web/test-runner": "^0.20.0", - "browser-sync": "^3.0.2", - "jest": "^29.5.0", - "jest-environment-jsdom": "^29.5.0", - "karma": "^6.3.0", - "ng-packagr": "^19.0.0 || ^19.2.0-next.0", - "protractor": "^7.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "typescript": ">=5.5 <5.9" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "@angular/ssr": { - "optional": true - }, - "@web/test-runner": { - "optional": true - }, - "browser-sync": { - "optional": true - }, - "jest": { - "optional": true - }, - "jest-environment-jsdom": { - "optional": true - }, - "karma": { - "optional": true - }, - "ng-packagr": { - "optional": true - }, - "protractor": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@angular-devkit/build-webpack": { - "version": "0.1902.19", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1902.19.tgz", - "integrity": "sha512-x2tlGg5CsUveFzuRuqeHknSbGirSAoRynEh+KqPRGK0G3WpMViW/M8SuVurecasegfIrDWtYZ4FnVxKqNbKwXQ==", - "dev": true, - "dependencies": { - "@angular-devkit/architect": "0.1902.19", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "webpack": "^5.30.0", - "webpack-dev-server": "^5.0.2" - } - }, - "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@angular-devkit/core": { - "version": "19.2.19", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.2.19.tgz", - "integrity": "sha512-JbLL+4IMLMBgjLZlnPG4lYDfz4zGrJ/s6Aoon321NJKuw1Kb1k5KpFu9dUY0BqLIe8xPQ2UJBpI+xXdK5MXMHQ==", - "dev": true, - "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.2", - "rxjs": "7.8.1", - "source-map": "0.7.4" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^4.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/core/node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/@angular-devkit/schematics": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.1.2.tgz", - "integrity": "sha512-PA3gkiFhHUuXd2XuP7yzKg/9N++bjw+uOl473KwIsMuZwMPhncKa4+mUYBaffDoPqaujZvjfo6mjtCBuiBv05w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.1.2", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.21", - "ora": "9.0.0", - "rxjs": "7.8.2" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.1.2.tgz", - "integrity": "sha512-0wl5nJlFWsbwfUB2CQeTSmnVQ8AtqqwM3bYPYtXSc+vA8+hzsOAjjDuRnBxZS9zTnqtXKXB1e7M3Iy7KUwh7LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.3", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular-devkit/schematics/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/cli-spinners": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz", - "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/log-symbols": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", - "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/ora": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.0.0.tgz", - "integrity": "sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.6.2", - "cli-cursor": "^5.0.0", - "cli-spinners": "^3.2.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.1.0", - "log-symbols": "^7.0.1", - "stdin-discarder": "^0.2.2", - "string-width": "^8.1.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/@angular-devkit/schematics/node_modules/string-width": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", - "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/animations": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.2.18.tgz", - "integrity": "sha512-c76x1t+OiSstPsvJdHmV8Q4taF+8SxWKqiY750fOjpd01it4jJbU6YQqIroC6Xie7154zZIxOTHH2uTj+nm5qA==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.2.18", - "@angular/core": "19.2.18" - } - }, - "node_modules/@angular/build": { - "version": "19.2.19", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.2.19.tgz", - "integrity": "sha512-SFzQ1bRkNFiOVu+aaz+9INmts7tDUrsHLEr9HmARXr9qk5UmR8prlw39p2u+Bvi6/lCiJ18TZMQQl9mGyr63lg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1902.19", - "@babel/core": "7.26.10", - "@babel/helper-annotate-as-pure": "7.25.9", - "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.26.0", - "@inquirer/confirm": "5.1.6", - "@vitejs/plugin-basic-ssl": "1.2.0", - "beasties": "0.3.2", - "browserslist": "^4.23.0", - "esbuild": "0.25.4", - "fast-glob": "3.3.3", - "https-proxy-agent": "7.0.6", - "istanbul-lib-instrument": "6.0.3", - "listr2": "8.2.5", - "magic-string": "0.30.17", - "mrmime": "2.0.1", - "parse5-html-rewriting-stream": "7.0.0", - "picomatch": "4.0.2", - "piscina": "4.8.0", - "rollup": "4.34.8", - "sass": "1.85.0", - "semver": "7.7.1", - "source-map-support": "0.5.21", - "vite": "6.4.1", - "watchpack": "2.4.2" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "optionalDependencies": { - "lmdb": "3.2.6" - }, - "peerDependencies": { - "@angular/compiler": "^19.0.0 || ^19.2.0-next.0", - "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", - "@angular/localize": "^19.0.0 || ^19.2.0-next.0", - "@angular/platform-server": "^19.0.0 || ^19.2.0-next.0", - "@angular/service-worker": "^19.0.0 || ^19.2.0-next.0", - "@angular/ssr": "^19.2.19", - "karma": "^6.4.0", - "less": "^4.2.0", - "ng-packagr": "^19.0.0 || ^19.2.0-next.0", - "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", - "typescript": ">=5.5 <5.9" - }, - "peerDependenciesMeta": { - "@angular/localize": { - "optional": true - }, - "@angular/platform-server": { - "optional": true - }, - "@angular/service-worker": { - "optional": true - }, - "@angular/ssr": { - "optional": true - }, - "karma": { - "optional": true - }, - "less": { - "optional": true - }, - "ng-packagr": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tailwindcss": { - "optional": true - } - } - }, - "node_modules/@angular/cli": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.1.2.tgz", - "integrity": "sha512-AHjXCBl2PEilMJct6DX3ih5Fl5PiKpNDIj0ViTyVh1YcfpYjt6NzhVlV2o++8VNPNH/vMcmf2551LZIDProXXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/architect": "0.2101.2", - "@angular-devkit/core": "21.1.2", - "@angular-devkit/schematics": "21.1.2", - "@inquirer/prompts": "7.10.1", - "@listr2/prompt-adapter-inquirer": "3.0.5", - "@modelcontextprotocol/sdk": "1.25.2", - "@schematics/angular": "21.1.2", - "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.46.2", - "ini": "6.0.0", - "jsonc-parser": "3.3.1", - "listr2": "9.0.5", - "npm-package-arg": "13.0.2", - "pacote": "21.0.4", - "parse5-html-rewriting-stream": "8.0.0", - "resolve": "1.22.11", - "semver": "7.7.3", - "yargs": "18.0.0", - "zod": "4.3.5" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.2101.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2101.2.tgz", - "integrity": "sha512-pV2onJgp16xO0vAqEfRWVynRPPLVHydYLANNa3UX3l5T39JcYdMIoOHSIIl8tWrxVeOwiWd1ajub0VsFTUok4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.1.2", - "rxjs": "7.8.2" - }, - "bin": { - "architect": "bin/cli.js" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.1.2.tgz", - "integrity": "sha512-0wl5nJlFWsbwfUB2CQeTSmnVQ8AtqqwM3bYPYtXSc+vA8+hzsOAjjDuRnBxZS9zTnqtXKXB1e7M3Iy7KUwh7LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.3", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@angular/cli/node_modules/@listr2/prompt-adapter-inquirer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-3.0.5.tgz", - "integrity": "sha512-WELs+hj6xcilkloBXYf9XXK8tYEnKsgLj01Xl5ONUJpKjmT5hGVUzNUS5tooUxs7pGMrw+jFD/41WpqW4V3LDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8", - "listr2": "9.0.5" - } - }, - "node_modules/@angular/cli/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/cli-truncate": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.1.tgz", - "integrity": "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^7.1.0", - "string-width": "^8.0.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/cli/node_modules/cli-truncate/node_modules/string-width": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.1.tgz", - "integrity": "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/cli/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/@angular/cli/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@angular/cli/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@angular/cli/node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^5.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@angular/cli/node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/parse5-html-rewriting-stream": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", - "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "entities": "^6.0.0", - "parse5": "^8.0.0", - "parse5-sax-parser": "^8.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/parse5-sax-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", - "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^8.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@angular/cli/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@angular/cli/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/@angular/cli/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@angular/cli/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/cli/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/@angular/common": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.2.18.tgz", - "integrity": "sha512-CrV02Omzw/QtfjlEVXVPJVXipdx83NuA+qSASZYrxrhKFusUZyK3P/Zznqg+wiAeNDbedQwMUVqoAARHf0xQrw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "19.2.18", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/compiler": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.2.18.tgz", - "integrity": "sha512-3MscvODxRVxc3Cs0ZlHI5Pk5rEvE80otfvxZTMksOZuPlv1B+S8MjWfc3X3jk9SbyUEzODBEH55iCaBHD48V3g==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - } - }, - "node_modules/@angular/compiler-cli": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.2.18.tgz", - "integrity": "sha512-N4TMtLfImJIoMaRL6mx7885UBeQidywptHH6ACZj71Ar6++DBc1mMlcwuvbeJCd3r3y8MQ5nLv5PZSN/tHr13w==", - "dev": true, - "dependencies": { - "@babel/core": "7.26.9", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^4.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" - }, - "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js", - "ngcc": "bundles/ngcc/index.js" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/compiler": "19.2.18", - "typescript": ">=5.5 <5.9" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.9", - "@babel/types": "^7.26.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@angular/core": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.2.18.tgz", - "integrity": "sha512-+QRrf0Igt8ccUWXHA+7doK5W6ODyhHdqVyblSlcQ8OciwkzIIGGEYNZom5OZyWMh+oI54lcSeyV2O3xaDepSrQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0" - } - }, - "node_modules/@angular/forms": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.2.18.tgz", - "integrity": "sha512-pe40934jWhoS7DyGl7jyZdoj1gvBgur2t1zrJD+csEkTitYnW14+La2Pv6SW1pNX5nIzFsgsS9Nex1KcH5S6Tw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.2.18", - "@angular/core": "19.2.18", - "@angular/platform-browser": "19.2.18", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@angular/platform-browser": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.2.18.tgz", - "integrity": "sha512-eahtsHPyXTYLARs9YOlXhnXGgzw0wcyOcDkBvNWK/3lA0NHIgIHmQgXAmBo+cJ+g9skiEQTD2OmSrrwbFKWJkw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/animations": "19.2.18", - "@angular/common": "19.2.18", - "@angular/core": "19.2.18" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } - } - }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.2.18.tgz", - "integrity": "sha512-wqDtK2yVN5VDqVeOSOfqELdu40fyoIDknBGSxA27CEXzFVdMWJyIpuvUi+GMa+9eGjlS+1uVVBaRwxmnuvHj+A==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.2.18", - "@angular/compiler": "19.2.18", - "@angular/core": "19.2.18", - "@angular/platform-browser": "19.2.18" - } - }, - "node_modules/@angular/router": { - "version": "19.2.18", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.2.18.tgz", - "integrity": "sha512-7cimxtPODSwokFQ0TRYzX0ad8Yjrl0MJfzaDCJejd1n/q7RZ7KZmHd0DS/LkDNXVMEh4swr00fK+3YWG/Szsrg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.2.18", - "@angular/core": "19.2.18", - "@angular/platform-browser": "19.2.18", - "rxjs": "^6.5.3 || ^7.4.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", - "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.26.10", - "@babel/types": "^7.26.10", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "regexpu-core": "^6.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "debug": "^4.4.3", - "lodash.debounce": "^4.0.8", - "resolve": "^1.22.11" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", - "dev": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", - "dev": true, - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", - "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.26.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", - "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", - "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz", - "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", - "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.26.8", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.26.5", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.26.3", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.26.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.26.3", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.26.8", - "@babel/plugin-transform-typeof-symbol": "^7.26.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", - "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", - "dev": true, - "engines": { - "node": ">=14.17.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "hono": "^4" - } - }, - "node_modules/@inquirer/ansi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", - "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", - "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.6.tgz", - "integrity": "sha512-6ZXYK3M1XmaVBZX6FCfChgtponnL0R6I7k8Nu+kaoNkT828FVZTcca1MqmWQipaW2oNREQl5AaPCUOOCVNdRMw==", - "dev": true, - "dependencies": { - "@inquirer/core": "^10.1.7", - "@inquirer/type": "^3.0.4" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", - "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", - "dev": true, - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", - "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor": { - "version": "4.2.23", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", - "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/external-editor": "^1.0.3", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", - "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", - "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^2.1.1", - "iconv-lite": "^0.7.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", - "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", - "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password": { - "version": "4.0.23", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", - "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts/node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", - "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", - "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/select": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", - "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/ansi": "^1.0.2", - "@inquirer/core": "^10.3.2", - "@inquirer/figures": "^1.0.15", - "@inquirer/type": "^3.0.10", - "yoctocolors-cjs": "^2.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", - "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz", - "integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@jsonjoy.com/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/buffers": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.65.0.tgz", - "integrity": "sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/codegen": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", - "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-core": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.10.tgz", - "integrity": "sha512-PyAEA/3cnHhsGcdY+AmIU+ZPqTuZkDhCXQ2wkXypdLitSpd6d5Ivxhnq4wa2ETRWFVJGabYynBWxIijOswSmOw==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "thingies": "^2.5.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.10.tgz", - "integrity": "sha512-/FVK63ysNzTPOnCCcPoPHt77TOmachdMS422txM4KhxddLdbW1fIbFMYH0AM0ow/YchCyS5gqEjKLNyv71j/5Q==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "thingies": "^2.5.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-node": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.10.tgz", - "integrity": "sha512-7R4Gv3tkUdW3dXfXiOkqxkElxKNVdd8BDOWC0/dbERd0pXpPY+s2s1Mino+aTvkGrFPiY+mmVxA7zhskm4Ue4Q==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", - "glob-to-regex.js": "^1.0.0", - "thingies": "^2.5.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.10.tgz", - "integrity": "sha512-uUnKz8R0YJyKq5jXpZtkGV9U0pJDt8hmYcLRrPjROheIfjMXsz82kXMgAA/qNg0wrZ1Kv+hrg7azqEZx6XZCVw==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.10.tgz", - "integrity": "sha512-oH+O6Y4lhn9NyG6aEoFwIBNKZeYy66toP5LJcDOMBgL99BKQMUf/zWJspdRhMdn/3hbzQsZ8EHHsuekbFLGUWw==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.10.tgz", - "integrity": "sha512-8EuPBgVI2aDPwFdaNQeNpHsyqPi3rr+85tMNG/lHvQLiVjzoZsvxA//Xd8aB567LUhy4QS03ptT+unkD/DIsNg==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.10" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-print": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.10.tgz", - "integrity": "sha512-JW4fp5mAYepzFsSGrQ48ep8FXxpg4niFWHdF78wDrFGof7F3tKDJln72QFDEn/27M1yHd4v7sKHHVPh78aWcEw==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.56.10", - "tree-dump": "^1.1.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.10.tgz", - "integrity": "sha512-DkR6l5fj7+qj0+fVKm/OOXMGfDFCGXLfyHkORH3DF8hxkpDgIHbhf/DwncBMs2igu/ST7OEkexn1gIqoU6Y+9g==", - "dev": true, - "dependencies": { - "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/json-pack": "^17.65.0", - "@jsonjoy.com/util": "^17.65.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.65.0.tgz", - "integrity": "sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.65.0.tgz", - "integrity": "sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.65.0.tgz", - "integrity": "sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ==", - "dev": true, - "dependencies": { - "@jsonjoy.com/base64": "17.65.0", - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0", - "@jsonjoy.com/json-pointer": "17.65.0", - "@jsonjoy.com/util": "17.65.0", - "hyperdyperid": "^1.2.0", - "thingies": "^2.5.0", - "tree-dump": "^1.1.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.65.0.tgz", - "integrity": "sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow==", - "dev": true, - "dependencies": { - "@jsonjoy.com/util": "17.65.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { - "version": "17.65.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.65.0.tgz", - "integrity": "sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w==", - "dev": true, - "dependencies": { - "@jsonjoy.com/buffers": "17.65.0", - "@jsonjoy.com/codegen": "17.65.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/json-pack": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", - "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", - "dev": true, - "dependencies": { - "@jsonjoy.com/base64": "^1.1.2", - "@jsonjoy.com/buffers": "^1.2.0", - "@jsonjoy.com/codegen": "^1.0.0", - "@jsonjoy.com/json-pointer": "^1.0.2", - "@jsonjoy.com/util": "^1.9.0", - "hyperdyperid": "^1.2.0", - "thingies": "^2.5.0", - "tree-dump": "^1.1.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", - "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/json-pointer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", - "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", - "dev": true, - "dependencies": { - "@jsonjoy.com/codegen": "^1.0.0", - "@jsonjoy.com/util": "^1.9.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/util": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", - "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", - "dev": true, - "dependencies": { - "@jsonjoy.com/buffers": "^1.0.0", - "@jsonjoy.com/codegen": "^1.0.0" - }, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", - "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "dev": true - }, - "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.2.6.tgz", - "integrity": "sha512-yF/ih9EJJZc72psFQbwnn8mExIWfTnzWJg+N02hnpXtDPETYLmQswIMBn7+V88lfCaFrMozJsUvcEQIkEPU0Gg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.2.6.tgz", - "integrity": "sha512-5BbCumsFLbCi586Bb1lTWQFkekdQUw8/t8cy++Uq251cl3hbDIGEwD9HAwh8H6IS2F6QA9KdKmO136LmipRNkg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.2.6.tgz", - "integrity": "sha512-+6XgLpMb7HBoWxXj+bLbiiB4s0mRRcDPElnRS3LpWRzdYSe+gFk5MT/4RrVNqd2MESUDmb53NUXw1+BP69bjiQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.2.6.tgz", - "integrity": "sha512-l5VmJamJ3nyMmeD1ANBQCQqy7do1ESaJQfKPSm2IG9/ADZryptTyCj8N6QaYgIWewqNUrcbdMkJajRQAt5Qjfg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.2.6.tgz", - "integrity": "sha512-nDYT8qN9si5+onHYYaI4DiauDMx24OAiuZAUsEqrDy+ja/3EbpXPX/VAkMV8AEaQhy3xc4dRC+KcYIvOFefJ4Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.2.6.tgz", - "integrity": "sha512-XlqVtILonQnG+9fH2N3Aytria7P/1fwDgDhl29rde96uH2sLB8CHORIf2PfuLVzFQJ7Uqp8py9AYwr3ZUCFfWg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.25.2", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz", - "integrity": "sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@hono/node-server": "^1.19.7", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.5", - "eventsource": "^3.0.2", - "eventsource-parser": "^3.0.0", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "jose": "^6.1.1", - "json-schema-typed": "^8.0.2", - "pkce-challenge": "^5.0.0", - "raw-body": "^3.0.0", - "zod": "^3.25 || ^4.0", - "zod-to-json-schema": "^3.25.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@cfworker/json-schema": "^4.1.1", - "zod": "^3.25 || ^4.0" - }, - "peerDependenciesMeta": { - "@cfworker/json-schema": { - "optional": true - }, - "zod": { - "optional": false - } - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", - "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", - "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.2.1", - "content-disposition": "^1.0.0", - "content-type": "^1.0.5", - "cookie": "^0.7.1", - "cookie-signature": "^1.2.1", - "debug": "^4.4.0", - "depd": "^2.0.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "finalhandler": "^2.1.0", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "merge-descriptors": "^2.0.0", - "mime-types": "^3.0.0", - "on-finished": "^2.4.1", - "once": "^1.4.0", - "parseurl": "^1.3.3", - "proxy-addr": "^2.0.7", - "qs": "^6.14.0", - "range-parser": "^1.2.1", - "router": "^2.2.0", - "send": "^1.1.0", - "serve-static": "^2.2.0", - "statuses": "^2.0.1", - "type-is": "^2.0.1", - "vary": "^1.1.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", - "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz", - "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz", - "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz", - "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz", - "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz", - "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz", - "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@napi-rs/nice": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", - "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "optionalDependencies": { - "@napi-rs/nice-android-arm-eabi": "1.1.1", - "@napi-rs/nice-android-arm64": "1.1.1", - "@napi-rs/nice-darwin-arm64": "1.1.1", - "@napi-rs/nice-darwin-x64": "1.1.1", - "@napi-rs/nice-freebsd-x64": "1.1.1", - "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", - "@napi-rs/nice-linux-arm64-gnu": "1.1.1", - "@napi-rs/nice-linux-arm64-musl": "1.1.1", - "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", - "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", - "@napi-rs/nice-linux-s390x-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-gnu": "1.1.1", - "@napi-rs/nice-linux-x64-musl": "1.1.1", - "@napi-rs/nice-openharmony-arm64": "1.1.1", - "@napi-rs/nice-win32-arm64-msvc": "1.1.1", - "@napi-rs/nice-win32-ia32-msvc": "1.1.1", - "@napi-rs/nice-win32-x64-msvc": "1.1.1" - } - }, - "node_modules/@napi-rs/nice-android-arm-eabi": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", - "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-android-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", - "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", - "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-darwin-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", - "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-freebsd-x64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", - "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", - "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", - "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-arm64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", - "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-ppc64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", - "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-riscv64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", - "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-s390x-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", - "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-gnu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", - "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-linux-x64-musl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", - "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-openharmony-arm64": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", - "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-arm64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", - "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-ia32-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", - "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/nice-win32-x64-msvc": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", - "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@ngtools/webpack": { - "version": "19.2.19", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.2.19.tgz", - "integrity": "sha512-R9aeTrOBiRVl8I698JWPniUAAEpSvzc8SUGWSM5UXWMcHnWqd92cOnJJ1aXDGJZKXrbhMhCBx9Dglmcks5IDpg==", - "dev": true, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^19.0.0 || ^19.2.0-next.0", - "typescript": ">=5.5 <5.9", - "webpack": "^5.54.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.0.tgz", - "integrity": "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==", - "dev": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^11.2.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/agent/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/fs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", - "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.1.tgz", - "integrity": "sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^9.0.0", - "ini": "^6.0.0", - "lru-cache": "^11.2.1", - "npm-pick-manifest": "^11.0.1", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/git/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/installed-package-contents": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", - "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^5.0.0", - "npm-normalize-package-bin": "^5.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", - "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.4.tgz", - "integrity": "sha512-0wInJG3j/K40OJt/33ax47WfWMzZTm6OQxB9cDhTt5huCP2a9g2GnlsxmfN+PulItNPIpPrZ+kfwwUil7eHcZQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "glob": "^13.0.0", - "hosted-git-info": "^9.0.0", - "json-parse-even-better-errors": "^5.0.0", - "proc-log": "^6.0.0", - "semver": "^7.5.3", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/package-json/node_modules/glob": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz", - "integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.1.2", - "minipass": "^7.1.2", - "path-scurry": "^2.0.0" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/package-json/node_modules/minimatch": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", - "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/promise-spawn": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", - "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/redact": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", - "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/run-script": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.3.tgz", - "integrity": "sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^5.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "node-gyp": "^12.1.0", - "proc-log": "^6.0.0", - "which": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@npmcli/run-script/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/@npmcli/run-script/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", - "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", - "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", - "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher/node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "optional": true - }, - "node_modules/@parcel/watcher/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz", - "integrity": "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz", - "integrity": "sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz", - "integrity": "sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz", - "integrity": "sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz", - "integrity": "sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz", - "integrity": "sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz", - "integrity": "sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz", - "integrity": "sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz", - "integrity": "sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz", - "integrity": "sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.1.tgz", - "integrity": "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.1.tgz", - "integrity": "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz", - "integrity": "sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz", - "integrity": "sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.1.tgz", - "integrity": "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.1.tgz", - "integrity": "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz", - "integrity": "sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.1.tgz", - "integrity": "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz", - "integrity": "sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz", - "integrity": "sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz", - "integrity": "sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.1.tgz", - "integrity": "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.1.tgz", - "integrity": "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz", - "integrity": "sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz", - "integrity": "sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.1.tgz", - "integrity": "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz", - "integrity": "sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@schematics/angular": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.1.2.tgz", - "integrity": "sha512-kxwxhCIUrj7DfzEtDSs/pi/w+aII/WQLpPfLgoQCWE8/95v60WnTfd1afmsXsFoxikKPxkwoPWtU2YbhSoX9MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@angular-devkit/core": "21.1.2", - "@angular-devkit/schematics": "21.1.2", - "jsonc-parser": "3.3.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "21.1.2", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.1.2.tgz", - "integrity": "sha512-0wl5nJlFWsbwfUB2CQeTSmnVQ8AtqqwM3bYPYtXSc+vA8+hzsOAjjDuRnBxZS9zTnqtXKXB1e7M3Iy7KUwh7LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "8.17.1", - "ajv-formats": "3.0.1", - "jsonc-parser": "3.3.1", - "picomatch": "4.0.3", - "rxjs": "7.8.2", - "source-map": "0.7.6" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "chokidar": "^5.0.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } - } - }, - "node_modules/@schematics/angular/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@schematics/angular/node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/@sigstore/bundle": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", - "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.1.0.tgz", - "integrity": "sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.0.tgz", - "integrity": "sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.0.tgz", - "integrity": "sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0", - "make-fetch-happen": "^15.0.3", - "proc-log": "^6.1.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/tuf": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz", - "integrity": "sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.5.0", - "tuf-js": "^4.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sigstore/verify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.0.tgz", - "integrity": "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "dev": true - }, - "node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", - "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", - "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^10.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", - "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", - "dev": true, - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dev": true, - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/express": { - "version": "4.17.25", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", - "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", - "dev": true, - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "^1" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", - "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/http-errors": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", - "dev": true - }, - "node_modules/@types/http-proxy": { - "version": "1.17.17", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", - "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/jasmine": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.15.tgz", - "integrity": "sha512-ZAC8KjmV2MJxbNTrwXFN+HKeajpXQZp6KpPiR6Aa4XvaEnjP6qh23lL/Rqb7AYzlp3h/rcwDrQ7Gg7q28cQTQg==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "dev": true - }, - "node_modules/@types/node": { - "version": "25.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", - "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", - "dev": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.14", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", - "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", - "dev": true - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "dev": true - }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true - }, - "node_modules/@types/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", - "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dev": true, - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", - "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", - "dev": true, - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "<1" - } - }, - "node_modules/@types/serve-static/node_modules/@types/send": { - "version": "0.17.6", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", - "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", - "dev": true, - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vitejs/plugin-basic-ssl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.2.0.tgz", - "integrity": "sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==", - "dev": true, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "node_modules/abbrev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", - "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/algoliasearch": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.2.tgz", - "integrity": "sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@algolia/abtesting": "1.12.2", - "@algolia/client-abtesting": "5.46.2", - "@algolia/client-analytics": "5.46.2", - "@algolia/client-common": "5.46.2", - "@algolia/client-insights": "5.46.2", - "@algolia/client-personalization": "5.46.2", - "@algolia/client-query-suggestions": "5.46.2", - "@algolia/client-search": "5.46.2", - "@algolia/ingestion": "1.46.2", - "@algolia/monitoring": "1.46.2", - "@algolia/recommend": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", - "dev": true, - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/babel-loader": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", - "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", - "dev": true, - "dependencies": { - "find-cache-dir": "^4.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", - "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.6", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", - "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true, - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "dev": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "node_modules/beasties": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.3.2.tgz", - "integrity": "sha512-p4AF8uYzm9Fwu8m/hSVTCPXrRBPmB34hQpHsec2KOaR9CZmgoU8IOv4Cvwq4hgz2p4hLMNbsdNl5XeA6XbAQwA==", - "dev": true, - "dependencies": { - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "htmlparser2": "^10.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.49", - "postcss-media-query-parser": "^0.2.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", - "dev": true, - "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacache": { - "version": "20.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.3.tgz", - "integrity": "sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^5.0.0", - "fs-minipass": "^3.0.0", - "glob": "^13.0.0", - "lru-cache": "^11.1.0", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^13.0.0", - "unique-filename": "^5.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.1.tgz", - "integrity": "sha512-B7U/vJpE3DkJ5WXTgTpTRN63uV42DseiXXKMwG14LQBXmsdeIoHAPbU/MEo6II0k5ED74uc2ZGTC6MwHFQhF6w==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "minimatch": "^10.1.2", - "minipass": "^7.1.2", - "path-scurry": "^2.0.0" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", - "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001768", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001768.tgz", - "integrity": "sha512-qY3aDRZC5nWPgHUgIB84WL+nySuo19wk0VJpp/XI9T34lrvkyhRvNVOFJOp2kxClQhiFBu+TaUSudf6oa3vkSA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chardet": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", - "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", - "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", - "dev": true, - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.1.0", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/compression/node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", - "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", - "dev": true - }, - "node_modules/copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "dependencies": { - "is-what": "^3.14.1" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/copy-webpack-plugin": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-12.0.2.tgz", - "integrity": "sha512-SNwdBeHyII+rWvee/bTnAYyO8vfVdcSTud4EIb6jcZ8inLeWucJE0DnxXQBjlQ5zlteuuvooGQy3LIyGxhvlOA==", - "dev": true, - "dependencies": { - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.1", - "globby": "^14.0.0", - "normalize-path": "^3.0.0", - "schema-utils": "^4.2.0", - "serialize-javascript": "^6.0.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", - "dev": true, - "dependencies": { - "browserslist": "^4.28.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz", - "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", - "dev": true, - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-loader": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.2.tgz", - "integrity": "sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==", - "dev": true, - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.27.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", - "dev": true - }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/default-browser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", - "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", - "dev": true, - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", - "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "node_modules/di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", - "dev": true - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dev": true, - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", - "dev": true, - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/engine.io": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", - "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", - "dev": true, - "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.18.3" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.2.tgz", - "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "punycode": "^1.4.1", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/esbuild-wasm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.25.4.tgz", - "integrity": "sha512-2HlCS6rNvKWaSKhWaG/YIyRsTsL3gUrMP2ToZMBIjw9LM7vVcIs+rz8kE2vExvTJgvM8OKPqNpcHawY/BQc/qQ==", - "dev": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/eventsource": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", - "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventsource-parser": "^3.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/eventsource-parser": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", - "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", - "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", - "proxy-addr": "~2.0.7", - "qs": "~6.14.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", - "setprototypeof": "1.2.0", - "statuses": "~2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express-rate-limit": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", - "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/express-rate-limit" - }, - "peerDependencies": { - "express": ">= 4.11" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/finalhandler": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", - "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "~2.4.1", - "parseurl": "~1.3.3", - "statuses": "~2.0.2", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/express/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "dev": true, - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regex.js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", - "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hono": { - "version": "4.11.7", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz", - "integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=16.9.0" - } - }, - "node_modules/hosted-git-info": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz", - "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^11.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/htmlparser2": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.2", - "entities": "^7.0.1" - } - }, - "node_modules/htmlparser2/node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "dev": true, - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", - "dev": true - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-proxy-middleware": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-3.0.5.tgz", - "integrity": "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.15", - "debug": "^4.3.6", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.3", - "is-plain-object": "^5.0.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/hyperdyperid": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", - "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", - "dev": true, - "engines": { - "node": ">=10.18" - } - }, - "node_modules/iconv-lite": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", - "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", - "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minimatch": "^10.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/ignore-walk/node_modules/minimatch": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.2.tgz", - "integrity": "sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immutable": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", - "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/ini": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", - "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/ipaddr.js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", - "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jasmine-core": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.2.tgz", - "integrity": "sha512-2oIUMGn00FdUiqz6epiiJr7xcFyNYj3rDcfmnzfkBnHyBQ3cBQUs4mmyGsOb7TTLb9kxk7dBcmEmqhDKkBoDyA==", - "dev": true - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", - "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-schema-typed": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.2.tgz", - "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/karma": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", - "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", - "dev": true, - "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.7.2", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/karma-chrome-launcher": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", - "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", - "dev": true, - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-coverage": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", - "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma-coverage/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/karma-jasmine": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", - "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", - "dev": true, - "dependencies": { - "jasmine-core": "^4.1.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "karma": "^6.0.0" - } - }, - "node_modules/karma-jasmine-html-reporter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", - "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", - "dev": true, - "peerDependencies": { - "jasmine-core": "^4.0.0 || ^5.0.0", - "karma": "^6.0.0", - "karma-jasmine": "^5.0.0" - } - }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", - "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", - "dev": true - }, - "node_modules/karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "dependencies": { - "source-map-support": "^0.5.5" - } - }, - "node_modules/karma/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/karma/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/karma/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/karma/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/karma/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/karma/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/karma/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/karma/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/launch-editor": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.12.0.tgz", - "integrity": "sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==", - "dev": true, - "dependencies": { - "picocolors": "^1.1.1", - "shell-quote": "^1.8.3" - } - }, - "node_modules/less": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.2.tgz", - "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==", - "dev": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/less-loader": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", - "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", - "dev": true, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/license-webpack-plugin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", - "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", - "dev": true, - "dependencies": { - "webpack-sources": "^3.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-sources": { - "optional": true - } - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/lmdb": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.2.6.tgz", - "integrity": "sha512-SuHqzPl7mYStna8WRotY8XX/EUZBjjv3QyKIByeCLFfC9uXT/OIHByEcA07PzbMfQAM0KYJtLgtpMRlIe5dErQ==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "msgpackr": "^1.11.2", - "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.5.3", - "weak-lru-cache": "^1.2.2" - }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.2.6", - "@lmdb/lmdb-darwin-x64": "3.2.6", - "@lmdb/lmdb-linux-arm": "3.2.6", - "@lmdb/lmdb-linux-arm64": "3.2.6", - "@lmdb/lmdb-linux-x64": "3.2.6", - "@lmdb/lmdb-win32-x64": "3.2.6" - } - }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", - "dev": true, - "dependencies": { - "get-east-asian-width": "^1.3.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", - "dev": true, - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-fetch-happen": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", - "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^4.0.0", - "cacache": "^20.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "4.56.10", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.10.tgz", - "integrity": "sha512-eLvzyrwqLHnLYalJP7YZ3wBe79MXktMdfQbvMrVD80K+NhrIukCVBvgP30zTJYEEDh9hZ/ep9z0KOdD7FSHo7w==", - "dev": true, - "dependencies": { - "@jsonjoy.com/fs-core": "4.56.10", - "@jsonjoy.com/fs-fsa": "4.56.10", - "@jsonjoy.com/fs-node": "4.56.10", - "@jsonjoy.com/fs-node-builtins": "4.56.10", - "@jsonjoy.com/fs-node-to-fsa": "4.56.10", - "@jsonjoy.com/fs-node-utils": "4.56.10", - "@jsonjoy.com/fs-print": "4.56.10", - "@jsonjoy.com/fs-snapshot": "4.56.10", - "@jsonjoy.com/json-pack": "^1.11.0", - "@jsonjoy.com/util": "^1.9.0", - "glob-to-regex.js": "^1.0.1", - "thingies": "^2.5.0", - "tree-dump": "^1.0.3", - "tslib": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", - "dev": true, - "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minipass-fetch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.1.tgz", - "integrity": "sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^2.0.0", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-sized": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", - "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", - "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/msgpackr": { - "version": "1.11.8", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.8.tgz", - "integrity": "sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==", - "dev": true, - "optional": true, - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" - } - }, - "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "dependencies": { - "node-gyp-build-optional-packages": "5.2.2" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" - } - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "dev": true, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/needle": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", - "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", - "dev": true, - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, - "optional": true - }, - "node_modules/node-forge": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.3.tgz", - "integrity": "sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-gyp": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.2.0.tgz", - "integrity": "sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^15.0.0", - "nopt": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "tar": "^7.5.4", - "tinyglobby": "^0.2.12", - "which": "^6.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", - "dev": true, - "optional": true, - "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" - } - }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true - }, - "node_modules/nopt": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", - "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^4.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-bundled": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", - "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^5.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-install-checks": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", - "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-package-arg": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", - "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", - "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^7.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-packlist": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.3.tgz", - "integrity": "sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==", - "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^8.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", - "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "npm-package-arg": "^13.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/npm-registry-fetch": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", - "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^4.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^15.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^13.0.0", - "proc-log": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", - "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", - "dev": true, - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ordered-binary": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", - "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", - "dev": true, - "optional": true - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "dev": true, - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz", - "integrity": "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", - "dev": true, - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/pacote": { - "version": "21.0.4", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.4.tgz", - "integrity": "sha512-RplP/pDW0NNNDh3pnaoIWYPvNenS7UqMbXyvMqJczosiFWTeGGwJC2NQBLqKf4rGLFfwCOnntw1aEp9Jiqm1MA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "@npmcli/installed-package-contents": "^4.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "@npmcli/run-script": "^10.0.0", - "cacache": "^20.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^13.0.0", - "npm-packlist": "^10.0.1", - "npm-pick-manifest": "^11.0.1", - "npm-registry-fetch": "^19.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^4.0.0", - "ssri": "^13.0.0", - "tar": "^7.4.3" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-json/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", - "dev": true, - "dependencies": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", - "dev": true, - "dependencies": { - "parse5": "^7.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-scurry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", - "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.2.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.5.tgz", - "integrity": "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true - }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/piscina": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.8.0.tgz", - "integrity": "sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==", - "dev": true, - "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" - } - }, - "node_modules/pkce-challenge": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } - }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "dependencies": { - "find-up": "^6.3.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-loader": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", - "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", - "dev": true, - "dependencies": { - "cosmiconfig": "^9.0.0", - "jiti": "^1.20.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/proc-log": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", - "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true, - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "dev": true, - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", - "dev": true, - "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", - "dev": true - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", - "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regex-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.1.tgz", - "integrity": "sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==", - "dev": true - }, - "node_modules/regexpu-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", - "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.2", - "regjsgen": "^0.8.0", - "regjsparser": "^0.13.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.2.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", - "dev": true, - "dependencies": { - "jsesc": "~3.1.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", - "dev": true, - "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.34.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz", - "integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.8", - "@rollup/rollup-android-arm64": "4.34.8", - "@rollup/rollup-darwin-arm64": "4.34.8", - "@rollup/rollup-darwin-x64": "4.34.8", - "@rollup/rollup-freebsd-arm64": "4.34.8", - "@rollup/rollup-freebsd-x64": "4.34.8", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.8", - "@rollup/rollup-linux-arm-musleabihf": "4.34.8", - "@rollup/rollup-linux-arm64-gnu": "4.34.8", - "@rollup/rollup-linux-arm64-musl": "4.34.8", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.8", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.8", - "@rollup/rollup-linux-riscv64-gnu": "4.34.8", - "@rollup/rollup-linux-s390x-gnu": "4.34.8", - "@rollup/rollup-linux-x64-gnu": "4.34.8", - "@rollup/rollup-linux-x64-musl": "4.34.8", - "@rollup/rollup-win32-arm64-msvc": "4.34.8", - "@rollup/rollup-win32-ia32-msvc": "4.34.8", - "@rollup/rollup-win32-x64-msvc": "4.34.8", - "fsevents": "~2.3.2" - } - }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/router/node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/run-applescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", - "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sass": { - "version": "1.85.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.85.0.tgz", - "integrity": "sha512-3ToiC1xZ1Y8aU7+CkgCI/tqyuPXEmYGJXO7H4uqp0xkLXUqp88rQQ4j1HmP37xSJLbCJPaIiv+cT1y+grssrww==", - "dev": true, - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, - "node_modules/sass-loader": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz", - "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==", - "dev": true, - "dependencies": { - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", - "dev": true, - "optional": true, - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dev": true, - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", - "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", - "dev": true, - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.4.1", - "range-parser": "~1.2.1", - "statuses": "~2.0.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/send/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", - "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", - "dev": true, - "dependencies": { - "accepts": "~1.3.8", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.8.0", - "mime-types": "~2.1.35", - "parseurl": "~1.3.3" - }, - "engines": { - "node": ">= 0.8.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dev": true, - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/serve-static": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", - "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", - "dev": true, - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "~0.19.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socket.io": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", - "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", - "dev": true, - "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", - "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", - "dev": true, - "dependencies": { - "debug": "~4.4.1", - "ws": "~8.18.3" - } - }, - "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", - "dev": true, - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", - "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", - "dev": true, - "dependencies": { - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.72.1" - } - }, - "node_modules/source-map-loader/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/ssri": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", - "integrity": "sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", - "dev": true, - "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tar": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", - "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/terser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", - "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", - "dev": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", - "dev": true, - "engines": { - "node": ">=10.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "^2" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "dev": true, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tree-dump": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", - "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", - "dev": true, - "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/tuf-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", - "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "4.1.0", - "debug": "^4.4.3", - "make-fetch-happen": "^15.0.1" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ua-parser-js": { - "version": "0.7.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", - "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "bin": { - "ua-parser-js": "script/cli.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", - "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", - "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-filename": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-5.0.0.tgz", - "integrity": "sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/unique-slug": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-6.0.0.tgz", - "integrity": "sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", - "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.1.tgz", - "integrity": "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.1.tgz", - "integrity": "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.1.tgz", - "integrity": "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.1.tgz", - "integrity": "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.1.tgz", - "integrity": "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.1.tgz", - "integrity": "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.1.tgz", - "integrity": "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.1.tgz", - "integrity": "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.1.tgz", - "integrity": "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.1.tgz", - "integrity": "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.1.tgz", - "integrity": "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.1.tgz", - "integrity": "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.1.tgz", - "integrity": "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.1.tgz", - "integrity": "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.1.tgz", - "integrity": "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.1.tgz", - "integrity": "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/vite/node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.1.tgz", - "integrity": "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/vite/node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true - }, - "node_modules/vite/node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/vite/node_modules/rollup": { - "version": "4.57.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", - "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.1", - "@rollup/rollup-android-arm64": "4.57.1", - "@rollup/rollup-darwin-arm64": "4.57.1", - "@rollup/rollup-darwin-x64": "4.57.1", - "@rollup/rollup-freebsd-arm64": "4.57.1", - "@rollup/rollup-freebsd-x64": "4.57.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", - "@rollup/rollup-linux-arm-musleabihf": "4.57.1", - "@rollup/rollup-linux-arm64-gnu": "4.57.1", - "@rollup/rollup-linux-arm64-musl": "4.57.1", - "@rollup/rollup-linux-loong64-gnu": "4.57.1", - "@rollup/rollup-linux-loong64-musl": "4.57.1", - "@rollup/rollup-linux-ppc64-gnu": "4.57.1", - "@rollup/rollup-linux-ppc64-musl": "4.57.1", - "@rollup/rollup-linux-riscv64-gnu": "4.57.1", - "@rollup/rollup-linux-riscv64-musl": "4.57.1", - "@rollup/rollup-linux-s390x-gnu": "4.57.1", - "@rollup/rollup-linux-x64-gnu": "4.57.1", - "@rollup/rollup-linux-x64-musl": "4.57.1", - "@rollup/rollup-openbsd-x64": "4.57.1", - "@rollup/rollup-openharmony-arm64": "4.57.1", - "@rollup/rollup-win32-arm64-msvc": "4.57.1", - "@rollup/rollup-win32-ia32-msvc": "4.57.1", - "@rollup/rollup-win32-x64-gnu": "4.57.1", - "@rollup/rollup-win32-x64-msvc": "4.57.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dev": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/weak-lru-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", - "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", - "dev": true, - "optional": true - }, - "node_modules/webpack": { - "version": "5.98.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", - "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", - "dev": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz", - "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==", - "dev": true, - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^4.6.0", - "mime-types": "^2.1.31", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.2.tgz", - "integrity": "sha512-QcQ72gh8a+7JO63TAx/6XZf/CWhgMzu5m0QirvPfGvptOusAxG12w2+aua1Jkjr7hzaWDnJ2n6JFeexMHI+Zjg==", - "dev": true, - "dependencies": { - "@types/bonjour": "^3.5.13", - "@types/connect-history-api-fallback": "^1.5.4", - "@types/express": "^4.17.21", - "@types/express-serve-static-core": "^4.17.21", - "@types/serve-index": "^1.9.4", - "@types/serve-static": "^1.15.5", - "@types/sockjs": "^0.3.36", - "@types/ws": "^8.5.10", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.2.1", - "chokidar": "^3.6.0", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "express": "^4.21.2", - "graceful-fs": "^4.2.6", - "http-proxy-middleware": "^2.0.9", - "ipaddr.js": "^2.1.0", - "launch-editor": "^2.6.1", - "open": "^10.0.3", - "p-retry": "^6.2.0", - "schema-utils": "^4.2.0", - "selfsigned": "^2.4.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.4.2", - "ws": "^8.18.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/webpack-dev-server/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", - "dev": true, - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/webpack-dev-server/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-subresource-integrity": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", - "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", - "dev": true, - "dependencies": { - "typed-assert": "^1.0.8" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", - "webpack": "^5.12.0" - }, - "peerDependenciesMeta": { - "html-webpack-plugin": { - "optional": true - } - } - }, - "node_modules/webpack/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "dev": true, - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - }, - "node_modules/zone.js": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.1.tgz", - "integrity": "sha512-XE96n56IQpJM7NAoXswY3XRLcWFW83xe0BiAOeMD7K5k5xecOeul3Qcpx6GqEeeHNkW5DWL5zOyTbEfB4eti8w==" - } - } -} diff --git a/cmd/bugseti/frontend/package.json b/cmd/bugseti/frontend/package.json deleted file mode 100644 index d5cdb888..00000000 --- a/cmd/bugseti/frontend/package.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "name": "bugseti", - "version": "0.1.0", - "private": true, - "scripts": { - "ng": "ng", - "start": "ng serve", - "dev": "ng serve --configuration development", - "build": "ng build --configuration production", - "build:dev": "ng build --configuration development", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "ng lint" - }, - "dependencies": { - "@angular/animations": "^19.1.0", - "@angular/common": "^19.1.0", - "@angular/compiler": "^19.1.0", - "@angular/core": "^19.1.0", - "@angular/forms": "^19.1.0", - "@angular/platform-browser": "^19.1.0", - "@angular/platform-browser-dynamic": "^19.1.0", - "@angular/router": "^19.1.0", - "rxjs": "~7.8.0", - "tslib": "^2.3.0", - "zone.js": "~0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.1.0", - "@angular/cli": "^21.1.2", - "@angular/compiler-cli": "^19.1.0", - "@types/jasmine": "~5.1.0", - "jasmine-core": "~5.1.0", - "karma": "~6.4.0", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "~2.2.0", - "karma-jasmine": "~5.1.0", - "karma-jasmine-html-reporter": "~2.1.0", - "typescript": "~5.5.2" - } -} diff --git a/cmd/bugseti/frontend/src/app/app.component.ts b/cmd/bugseti/frontend/src/app/app.component.ts deleted file mode 100644 index 48d645c3..00000000 --- a/cmd/bugseti/frontend/src/app/app.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component } from '@angular/core'; -import { RouterOutlet } from '@angular/router'; - -@Component({ - selector: 'app-root', - standalone: true, - imports: [RouterOutlet], - template: '', - styles: [` - :host { - display: block; - height: 100%; - } - `] -}) -export class AppComponent { - title = 'BugSETI'; -} diff --git a/cmd/bugseti/frontend/src/app/app.config.ts b/cmd/bugseti/frontend/src/app/app.config.ts deleted file mode 100644 index 628370af..00000000 --- a/cmd/bugseti/frontend/src/app/app.config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ApplicationConfig } from '@angular/core'; -import { provideRouter, withHashLocation } from '@angular/router'; -import { routes } from './app.routes'; - -export const appConfig: ApplicationConfig = { - providers: [ - provideRouter(routes, withHashLocation()) - ] -}; diff --git a/cmd/bugseti/frontend/src/app/app.routes.ts b/cmd/bugseti/frontend/src/app/app.routes.ts deleted file mode 100644 index 76725edb..00000000 --- a/cmd/bugseti/frontend/src/app/app.routes.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Routes } from '@angular/router'; - -export const routes: Routes = [ - { - path: '', - redirectTo: 'tray', - pathMatch: 'full' - }, - { - path: 'tray', - loadComponent: () => import('./tray/tray.component').then(m => m.TrayComponent) - }, - { - path: 'workbench', - loadComponent: () => import('./workbench/workbench.component').then(m => m.WorkbenchComponent) - }, - { - path: 'settings', - loadComponent: () => import('./settings/settings.component').then(m => m.SettingsComponent) - }, - { - path: 'onboarding', - loadComponent: () => import('./onboarding/onboarding.component').then(m => m.OnboardingComponent) - }, - { - path: 'jellyfin', - loadComponent: () => import('./jellyfin/jellyfin.component').then(m => m.JellyfinComponent) - } -]; diff --git a/cmd/bugseti/frontend/src/app/jellyfin/jellyfin.component.ts b/cmd/bugseti/frontend/src/app/jellyfin/jellyfin.component.ts deleted file mode 100644 index 95801067..00000000 --- a/cmd/bugseti/frontend/src/app/jellyfin/jellyfin.component.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { Component } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; -import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; - -type Mode = 'web' | 'stream'; - -@Component({ - selector: 'app-jellyfin', - standalone: true, - imports: [CommonModule, FormsModule], - template: ` -
-
-
-

Jellyfin Player

-

Quick embed for media.lthn.ai or any Jellyfin host.

-
-
- - -
-
- -
-
- - -
- -
-
- - -
-
- - -
-
- - -
-
- -
- - -
-
- -
- -
- -
- -

Set Item ID and API key to build stream URL.

-
-
- `, - styles: [` - .jellyfin { - display: flex; - flex-direction: column; - gap: var(--spacing-md); - padding: var(--spacing-md); - height: 100%; - overflow: auto; - background: var(--bg-secondary); - } - - .jellyfin__header { - display: flex; - align-items: center; - justify-content: space-between; - gap: var(--spacing-md); - } - - .jellyfin__header h1 { - margin-bottom: var(--spacing-xs); - } - - .mode-switch { - display: flex; - gap: var(--spacing-xs); - } - - .mode-switch .btn.is-active { - border-color: var(--accent-primary); - color: var(--accent-primary); - } - - .jellyfin__config { - display: flex; - flex-direction: column; - gap: var(--spacing-sm); - } - - .stream-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); - gap: var(--spacing-sm); - } - - .actions { - display: flex; - gap: var(--spacing-sm); - } - - .jellyfin__viewer { - flex: 1; - min-height: 420px; - padding: 0; - overflow: hidden; - } - - .jellyfin-frame, - .jellyfin-video { - border: 0; - width: 100%; - height: 100%; - min-height: 420px; - background: #000; - } - - .stream-hint { - padding: var(--spacing-md); - margin: 0; - } - `] -}) -export class JellyfinComponent { - mode: Mode = 'web'; - loaded = false; - - serverUrl = 'https://media.lthn.ai'; - itemId = ''; - apiKey = ''; - mediaSourceId = ''; - - safeWebUrl!: SafeResourceUrl; - streamUrl = ''; - - constructor(private sanitizer: DomSanitizer) { - this.safeWebUrl = this.sanitizer.bypassSecurityTrustResourceUrl('https://media.lthn.ai/web/index.html'); - } - - load(): void { - const base = this.normalizeBase(this.serverUrl); - this.safeWebUrl = this.sanitizer.bypassSecurityTrustResourceUrl(`${base}/web/index.html`); - this.streamUrl = this.buildStreamUrl(base); - this.loaded = true; - } - - reset(): void { - this.loaded = false; - this.itemId = ''; - this.apiKey = ''; - this.mediaSourceId = ''; - this.streamUrl = ''; - } - - private normalizeBase(value: string): string { - const raw = value.trim() || 'https://media.lthn.ai'; - const withProtocol = raw.startsWith('http://') || raw.startsWith('https://') ? raw : `https://${raw}`; - return withProtocol.replace(/\/+$/, ''); - } - - private buildStreamUrl(base: string): string { - if (!this.itemId.trim() || !this.apiKey.trim()) { - return ''; - } - - const url = new URL(`${base}/Videos/${encodeURIComponent(this.itemId.trim())}/stream`); - url.searchParams.set('api_key', this.apiKey.trim()); - url.searchParams.set('static', 'true'); - if (this.mediaSourceId.trim()) { - url.searchParams.set('MediaSourceId', this.mediaSourceId.trim()); - } - return url.toString(); - } -} diff --git a/cmd/bugseti/frontend/src/app/onboarding/onboarding.component.ts b/cmd/bugseti/frontend/src/app/onboarding/onboarding.component.ts deleted file mode 100644 index 7d95d7be..00000000 --- a/cmd/bugseti/frontend/src/app/onboarding/onboarding.component.ts +++ /dev/null @@ -1,457 +0,0 @@ -import { Component } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -@Component({ - selector: 'app-onboarding', - standalone: true, - imports: [CommonModule, FormsModule], - template: ` -
-
- -
-
B
-

Welcome to BugSETI

-

Distributed Bug Fixing - like SETI@home but for code

- -
-
- [1] -
- Find Issues -

We pull beginner-friendly issues from OSS projects you care about.

-
-
-
- [2] -
- Get Context -

AI prepares relevant context to help you understand each issue.

-
-
-
- [3] -
- Submit PRs -

Fix bugs and submit PRs with minimal friction.

-
-
-
- - -
- - -
-

Connect GitHub

-

BugSETI uses the GitHub CLI (gh) to interact with repositories.

- -
- {{ ghAuthenticated ? '[OK]' : '[!]' }} - {{ ghAuthenticated ? 'GitHub CLI authenticated' : 'GitHub CLI not detected' }} -
- -
-

To authenticate with GitHub CLI, run:

- gh auth login -

After authenticating, click "Check Again".

-
- -
- - -
-
- - -
-

Choose Repositories

-

Add repositories you want to contribute to.

- -
- - -
- -
-

Selected Repositories

-
- {{ repo }} - -
-
- -
-

Suggested Repositories

-
- -
-
- -
- - -
-
- - -
-
[OK]
-

You're All Set!

-

BugSETI is ready to help you contribute to open source.

- -
-

{{ selectedRepos.length }} repositories selected

-

Looking for issues with these labels:

-
- good first issue - help wanted - beginner-friendly -
-
- - -
-
- -
- - - - -
-
- `, - styles: [` - .onboarding { - display: flex; - flex-direction: column; - height: 100%; - background-color: var(--bg-primary); - } - - .onboarding-content { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - padding: var(--spacing-xl); - } - - .step { - max-width: 500px; - text-align: center; - } - - .step-icon, .complete-icon { - width: 80px; - height: 80px; - display: flex; - align-items: center; - justify-content: center; - margin: 0 auto var(--spacing-lg); - background: linear-gradient(135deg, var(--accent-primary), var(--accent-success)); - border-radius: var(--radius-lg); - font-size: 32px; - font-weight: bold; - color: white; - } - - .complete-icon { - background: var(--accent-success); - } - - h1 { - font-size: 28px; - margin-bottom: var(--spacing-sm); - } - - h2 { - font-size: 24px; - margin-bottom: var(--spacing-sm); - } - - .subtitle { - color: var(--text-secondary); - margin-bottom: var(--spacing-xl); - } - - .feature-list { - text-align: left; - margin-bottom: var(--spacing-xl); - } - - .feature { - display: flex; - gap: var(--spacing-md); - margin-bottom: var(--spacing-md); - padding: var(--spacing-md); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - } - - .feature-icon { - font-family: var(--font-mono); - color: var(--accent-primary); - font-weight: bold; - } - - .feature strong { - display: block; - margin-bottom: var(--spacing-xs); - } - - .feature p { - color: var(--text-secondary); - font-size: 13px; - margin: 0; - } - - .auth-status { - display: flex; - align-items: center; - justify-content: center; - gap: var(--spacing-sm); - padding: var(--spacing-md); - background-color: var(--bg-tertiary); - border-radius: var(--radius-md); - margin: var(--spacing-lg) 0; - } - - .auth-status.auth-success { - background-color: rgba(63, 185, 80, 0.15); - color: var(--accent-success); - } - - .status-icon { - font-family: var(--font-mono); - font-weight: bold; - } - - .auth-instructions { - text-align: left; - padding: var(--spacing-md); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - } - - .auth-instructions code { - display: block; - margin: var(--spacing-md) 0; - padding: var(--spacing-md); - background-color: var(--bg-tertiary); - } - - .auth-instructions .note { - color: var(--text-muted); - font-size: 13px; - margin: 0; - } - - .step-actions { - display: flex; - gap: var(--spacing-md); - justify-content: center; - margin-top: var(--spacing-xl); - } - - .repo-input { - display: flex; - gap: var(--spacing-sm); - margin-bottom: var(--spacing-lg); - } - - .repo-input .form-input { - flex: 1; - } - - .selected-repos, .suggested-repos { - text-align: left; - margin-bottom: var(--spacing-lg); - } - - .selected-repos h3, .suggested-repos h3 { - font-size: 12px; - text-transform: uppercase; - color: var(--text-muted); - margin-bottom: var(--spacing-sm); - } - - .repo-chip { - display: inline-flex; - align-items: center; - gap: var(--spacing-xs); - padding: var(--spacing-xs) var(--spacing-sm); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - margin-right: var(--spacing-xs); - margin-bottom: var(--spacing-xs); - } - - .repo-remove { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 0; - } - - .suggested-list { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-xs); - } - - .suggestion { - padding: var(--spacing-xs) var(--spacing-sm); - background-color: var(--bg-tertiary); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - color: var(--text-secondary); - cursor: pointer; - font-size: 13px; - } - - .suggestion:hover { - background-color: var(--bg-secondary); - border-color: var(--accent-primary); - } - - .summary { - padding: var(--spacing-lg); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - margin-bottom: var(--spacing-xl); - } - - .summary p { - margin-bottom: var(--spacing-sm); - } - - .label-list { - display: flex; - gap: var(--spacing-xs); - justify-content: center; - flex-wrap: wrap; - } - - .step-indicators { - display: flex; - justify-content: center; - gap: var(--spacing-sm); - padding: var(--spacing-lg); - } - - .indicator { - width: 8px; - height: 8px; - border-radius: 50%; - background-color: var(--border-color); - } - - .indicator.active { - background-color: var(--accent-primary); - } - - .indicator.current { - width: 24px; - border-radius: 4px; - } - - .btn--lg { - padding: var(--spacing-md) var(--spacing-xl); - font-size: 16px; - } - `] -}) -export class OnboardingComponent { - step = 1; - ghAuthenticated = false; - newRepo = ''; - selectedRepos: string[] = []; - suggestedRepos = [ - 'facebook/react', - 'microsoft/vscode', - 'golang/go', - 'kubernetes/kubernetes', - 'rust-lang/rust', - 'angular/angular', - 'nodejs/node', - 'python/cpython' - ]; - - ngOnInit() { - this.checkGhAuth(); - } - - nextStep() { - if (this.step < 4) { - this.step++; - } - } - - prevStep() { - if (this.step > 1) { - this.step--; - } - } - - async checkGhAuth() { - try { - // Check if gh CLI is authenticated - // In a real implementation, this would call the backend - this.ghAuthenticated = true; // Assume authenticated for demo - } catch (err) { - this.ghAuthenticated = false; - } - } - - addRepo() { - if (this.newRepo && !this.selectedRepos.includes(this.newRepo)) { - this.selectedRepos.push(this.newRepo); - this.newRepo = ''; - } - } - - removeRepo(index: number) { - this.selectedRepos.splice(index, 1); - } - - addSuggested(repo: string) { - if (!this.selectedRepos.includes(repo)) { - this.selectedRepos.push(repo); - } - } - - async complete() { - try { - // Save repos to config - if ((window as any).go?.main?.ConfigService?.SetConfig) { - const config = await (window as any).go.main.ConfigService.GetConfig() || {}; - config.watchedRepos = this.selectedRepos; - await (window as any).go.main.ConfigService.SetConfig(config); - } - - // Mark onboarding as complete - if ((window as any).go?.main?.TrayService?.CompleteOnboarding) { - await (window as any).go.main.TrayService.CompleteOnboarding(); - } - - // Close onboarding window and start fetching - if ((window as any).wails?.Window) { - (window as any).wails.Window.GetByName('onboarding').then((w: any) => w.Hide()); - } - - // Start fetching - if ((window as any).go?.main?.TrayService?.StartFetching) { - await (window as any).go.main.TrayService.StartFetching(); - } - } catch (err) { - console.error('Failed to complete onboarding:', err); - } - } -} diff --git a/cmd/bugseti/frontend/src/app/settings/settings.component.ts b/cmd/bugseti/frontend/src/app/settings/settings.component.ts deleted file mode 100644 index 7447d3fa..00000000 --- a/cmd/bugseti/frontend/src/app/settings/settings.component.ts +++ /dev/null @@ -1,407 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -interface Config { - watchedRepos: string[]; - labels: string[]; - fetchIntervalMinutes: number; - notificationsEnabled: boolean; - notificationSound: boolean; - workspaceDir: string; - marketplaceMcpRoot: string; - theme: string; - autoSeedContext: boolean; - workHours?: { - enabled: boolean; - startHour: number; - endHour: number; - days: number[]; - timezone: string; - }; -} - -@Component({ - selector: 'app-settings', - standalone: true, - imports: [CommonModule, FormsModule], - template: ` -
-
-

Settings

- -
- -
-
-

Repositories

-

Add GitHub repositories to watch for issues.

- -
-
- {{ repo }} - -
-
- -
- - -
-
- -
-

Issue Labels

-

Filter issues by these labels.

- -
- - {{ label }} - - -
- -
- - -
-
- -
-

Fetch Settings

- -
- - -
- -
- -
-
- -
-

Work Hours

-

Only fetch issues during these hours.

- -
- -
- -
-
- - -
- -
- - -
- -
- -
- -
-
-
-
- -
-

Notifications

- -
- -
- -
- -
-
- -
-

Appearance

- -
- - -
-
- -
-

Storage

- -
- - -
- -
- - -

Override the marketplace MCP root. Leave empty to auto-detect.

-
-
-
-
- `, - styles: [` - .settings { - display: flex; - flex-direction: column; - height: 100%; - background-color: var(--bg-secondary); - } - - .settings-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-md) var(--spacing-lg); - background-color: var(--bg-primary); - border-bottom: 1px solid var(--border-color); - } - - .settings-header h1 { - font-size: 18px; - margin: 0; - } - - .settings-content { - flex: 1; - overflow-y: auto; - padding: var(--spacing-lg); - } - - .settings-section { - background-color: var(--bg-primary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: var(--spacing-lg); - margin-bottom: var(--spacing-lg); - } - - .settings-section h2 { - font-size: 16px; - margin-bottom: var(--spacing-xs); - } - - .section-description { - color: var(--text-muted); - font-size: 13px; - margin-bottom: var(--spacing-md); - } - - .repo-list, .label-list { - margin-bottom: var(--spacing-md); - } - - .repo-item { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-sm); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - margin-bottom: var(--spacing-xs); - } - - .add-repo, .add-label { - display: flex; - gap: var(--spacing-sm); - } - - .add-repo .form-input, .add-label .form-input { - flex: 1; - } - - .label-list { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-xs); - } - - .label-chip { - display: inline-flex; - align-items: center; - gap: var(--spacing-xs); - padding: var(--spacing-xs) var(--spacing-sm); - background-color: var(--bg-tertiary); - border-radius: 999px; - font-size: 13px; - } - - .label-remove { - background: none; - border: none; - color: var(--text-muted); - cursor: pointer; - padding: 0; - font-size: 14px; - line-height: 1; - } - - .label-remove:hover { - color: var(--accent-danger); - } - - .checkbox-label { - display: flex; - align-items: center; - gap: var(--spacing-sm); - cursor: pointer; - } - - .checkbox-label input[type="checkbox"] { - width: 16px; - height: 16px; - } - - .work-hours-config { - display: grid; - grid-template-columns: 1fr 1fr; - gap: var(--spacing-md); - margin-top: var(--spacing-md); - } - - .day-checkboxes { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-sm); - } - - .day-checkboxes .checkbox-label { - width: auto; - } - - .btn--sm { - padding: var(--spacing-xs) var(--spacing-sm); - font-size: 12px; - } - `] -}) -export class SettingsComponent implements OnInit { - config: Config = { - watchedRepos: [], - labels: ['good first issue', 'help wanted'], - fetchIntervalMinutes: 15, - notificationsEnabled: true, - notificationSound: true, - workspaceDir: '', - marketplaceMcpRoot: '', - theme: 'dark', - autoSeedContext: true, - workHours: { - enabled: false, - startHour: 9, - endHour: 17, - days: [1, 2, 3, 4, 5], - timezone: '' - } - }; - - newRepo = ''; - newLabel = ''; - hours = Array.from({ length: 24 }, (_, i) => i); - days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; - - ngOnInit() { - this.loadConfig(); - } - - async loadConfig() { - try { - if ((window as any).go?.main?.ConfigService?.GetConfig) { - this.config = await (window as any).go.main.ConfigService.GetConfig(); - if (!this.config.workHours) { - this.config.workHours = { - enabled: false, - startHour: 9, - endHour: 17, - days: [1, 2, 3, 4, 5], - timezone: '' - }; - } - } - } catch (err) { - console.error('Failed to load config:', err); - } - } - - async saveSettings() { - try { - if ((window as any).go?.main?.ConfigService?.SetConfig) { - await (window as any).go.main.ConfigService.SetConfig(this.config); - alert('Settings saved!'); - } - } catch (err) { - console.error('Failed to save config:', err); - alert('Failed to save settings.'); - } - } - - addRepo() { - if (this.newRepo && !this.config.watchedRepos.includes(this.newRepo)) { - this.config.watchedRepos.push(this.newRepo); - this.newRepo = ''; - } - } - - removeRepo(index: number) { - this.config.watchedRepos.splice(index, 1); - } - - addLabel() { - if (this.newLabel && !this.config.labels.includes(this.newLabel)) { - this.config.labels.push(this.newLabel); - this.newLabel = ''; - } - } - - removeLabel(index: number) { - this.config.labels.splice(index, 1); - } - - isDaySelected(day: number): boolean { - return this.config.workHours?.days.includes(day) || false; - } - - toggleDay(day: number) { - if (!this.config.workHours) return; - - const index = this.config.workHours.days.indexOf(day); - if (index === -1) { - this.config.workHours.days.push(day); - } else { - this.config.workHours.days.splice(index, 1); - } - } -} diff --git a/cmd/bugseti/frontend/src/app/settings/updates.component.ts b/cmd/bugseti/frontend/src/app/settings/updates.component.ts deleted file mode 100644 index fb4edf94..00000000 --- a/cmd/bugseti/frontend/src/app/settings/updates.component.ts +++ /dev/null @@ -1,556 +0,0 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -interface UpdateSettings { - channel: string; - autoUpdate: boolean; - checkInterval: number; - lastCheck: string; -} - -interface VersionInfo { - version: string; - channel: string; - commit: string; - buildTime: string; - goVersion: string; - os: string; - arch: string; -} - -interface ChannelInfo { - id: string; - name: string; - description: string; -} - -interface UpdateCheckResult { - available: boolean; - currentVersion: string; - latestVersion: string; - release?: { - version: string; - channel: string; - tag: string; - name: string; - body: string; - publishedAt: string; - htmlUrl: string; - }; - error?: string; - checkedAt: string; -} - -@Component({ - selector: 'app-updates-settings', - standalone: true, - imports: [CommonModule, FormsModule], - template: ` -
-
-
- {{ versionInfo?.version || 'Unknown' }} - - {{ versionInfo?.channel || 'dev' }} - -
-

- Built {{ versionInfo.buildTime | date:'medium' }} ({{ versionInfo.commit?.substring(0, 7) }}) -

-
- -
-
-
!
-
-

Update Available

-

Version {{ checkResult.latestVersion }} is available

- - View Release Notes - -
- -
- -
-
OK
-
-

Up to Date

-

You're running the latest version

- - Last checked: {{ checkResult.checkedAt | date:'short' }} - -
-
- -
-
X
-
-

Check Failed

-

{{ checkResult.error }}

-
-
-
- -
- -
- -
-

Update Channel

-

Choose which release channel to follow for updates.

- -
- -
-
- -
-

Automatic Updates

- -
- -

When enabled, updates will be installed automatically on app restart.

-
- -
- - -
-
- -
- {{ saveMessage }} -
-
- `, - styles: [` - .updates-settings { - padding: var(--spacing-md); - } - - .current-version { - background: var(--bg-tertiary); - border-radius: var(--radius-lg); - padding: var(--spacing-lg); - margin-bottom: var(--spacing-lg); - text-align: center; - } - - .version-badge { - display: flex; - align-items: center; - justify-content: center; - gap: var(--spacing-sm); - margin-bottom: var(--spacing-xs); - } - - .version-number { - font-size: 24px; - font-weight: 600; - } - - .channel-badge { - padding: 2px 8px; - border-radius: 999px; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - } - - .channel-stable { background: var(--accent-success); color: white; } - .channel-beta { background: var(--accent-warning); color: black; } - .channel-nightly { background: var(--accent-purple, #8b5cf6); color: white; } - .channel-dev { background: var(--text-muted); color: var(--bg-primary); } - - .build-info { - color: var(--text-muted); - font-size: 12px; - margin: 0; - } - - .update-check { - margin-bottom: var(--spacing-lg); - } - - .update-available, .up-to-date, .check-error { - display: flex; - align-items: center; - gap: var(--spacing-md); - padding: var(--spacing-md); - border-radius: var(--radius-md); - } - - .update-available { - background: var(--accent-warning-bg, rgba(245, 158, 11, 0.1)); - border: 1px solid var(--accent-warning); - } - - .up-to-date { - background: var(--accent-success-bg, rgba(34, 197, 94, 0.1)); - border: 1px solid var(--accent-success); - } - - .check-error { - background: var(--accent-danger-bg, rgba(239, 68, 68, 0.1)); - border: 1px solid var(--accent-danger); - } - - .update-icon, .check-icon, .error-icon { - width: 40px; - height: 40px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-weight: bold; - flex-shrink: 0; - } - - .update-icon { background: var(--accent-warning); color: black; } - .check-icon { background: var(--accent-success); color: white; } - .error-icon { background: var(--accent-danger); color: white; } - - .update-info, .check-info, .error-info { - flex: 1; - } - - .update-info h4, .check-info h4, .error-info h4 { - margin: 0 0 var(--spacing-xs) 0; - font-size: 14px; - } - - .update-info p, .check-info p, .error-info p { - margin: 0; - font-size: 13px; - color: var(--text-muted); - } - - .release-link { - color: var(--accent-primary); - font-size: 12px; - } - - .last-check { - font-size: 11px; - color: var(--text-muted); - } - - .check-button-row { - margin-bottom: var(--spacing-lg); - } - - .settings-section { - background: var(--bg-primary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: var(--spacing-lg); - margin-bottom: var(--spacing-lg); - } - - .settings-section h3 { - font-size: 14px; - margin: 0 0 var(--spacing-xs) 0; - } - - .section-description { - color: var(--text-muted); - font-size: 12px; - margin-bottom: var(--spacing-md); - } - - .channel-options { - display: flex; - flex-direction: column; - gap: var(--spacing-sm); - } - - .channel-option { - display: flex; - align-items: flex-start; - gap: var(--spacing-sm); - padding: var(--spacing-md); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - cursor: pointer; - transition: all 0.15s ease; - } - - .channel-option:hover { - border-color: var(--accent-primary); - } - - .channel-option.selected { - border-color: var(--accent-primary); - background: var(--accent-primary-bg, rgba(59, 130, 246, 0.1)); - } - - .channel-option input[type="radio"] { - margin-top: 2px; - } - - .channel-content { - display: flex; - flex-direction: column; - gap: 2px; - } - - .channel-name { - font-weight: 500; - font-size: 14px; - } - - .channel-desc { - font-size: 12px; - color: var(--text-muted); - } - - .form-group { - margin-bottom: var(--spacing-md); - } - - .form-group:last-child { - margin-bottom: 0; - } - - .checkbox-label { - display: flex; - align-items: center; - gap: var(--spacing-sm); - cursor: pointer; - } - - .setting-hint { - color: var(--text-muted); - font-size: 12px; - margin: var(--spacing-xs) 0 0 24px; - } - - .form-label { - display: block; - font-size: 13px; - margin-bottom: var(--spacing-xs); - } - - .form-select { - width: 100%; - padding: var(--spacing-sm); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - background: var(--bg-secondary); - color: var(--text-primary); - font-size: 14px; - } - - .save-status { - text-align: center; - font-size: 13px; - color: var(--accent-success); - } - - .save-status .error { - color: var(--accent-danger); - } - - .btn { - padding: var(--spacing-sm) var(--spacing-md); - border: none; - border-radius: var(--radius-md); - font-size: 14px; - cursor: pointer; - transition: all 0.15s ease; - } - - .btn:disabled { - opacity: 0.6; - cursor: not-allowed; - } - - .btn--primary { - background: var(--accent-primary); - color: white; - } - - .btn--primary:hover:not(:disabled) { - background: var(--accent-primary-hover, #2563eb); - } - - .btn--secondary { - background: var(--bg-tertiary); - color: var(--text-primary); - border: 1px solid var(--border-color); - } - - .btn--secondary:hover:not(:disabled) { - background: var(--bg-secondary); - } - `] -}) -export class UpdatesComponent implements OnInit, OnDestroy { - settings: UpdateSettings = { - channel: 'stable', - autoUpdate: false, - checkInterval: 6, - lastCheck: '' - }; - - versionInfo: VersionInfo | null = null; - checkResult: UpdateCheckResult | null = null; - - channels: ChannelInfo[] = [ - { id: 'stable', name: 'Stable', description: 'Production releases - most stable, recommended for most users' }, - { id: 'beta', name: 'Beta', description: 'Pre-release builds - new features being tested before stable release' }, - { id: 'nightly', name: 'Nightly', description: 'Latest development builds - bleeding edge, may be unstable' } - ]; - - isChecking = false; - isInstalling = false; - saveMessage = ''; - saveError = false; - - private saveTimeout: ReturnType | null = null; - - ngOnInit() { - this.loadSettings(); - this.loadVersionInfo(); - } - - ngOnDestroy() { - if (this.saveTimeout) { - clearTimeout(this.saveTimeout); - } - } - - async loadSettings() { - try { - const wails = (window as any).go?.main; - if (wails?.UpdateService?.GetSettings) { - this.settings = await wails.UpdateService.GetSettings(); - } else if (wails?.ConfigService?.GetUpdateSettings) { - this.settings = await wails.ConfigService.GetUpdateSettings(); - } - } catch (err) { - console.error('Failed to load update settings:', err); - } - } - - async loadVersionInfo() { - try { - const wails = (window as any).go?.main; - if (wails?.VersionService?.GetVersionInfo) { - this.versionInfo = await wails.VersionService.GetVersionInfo(); - } else if (wails?.UpdateService?.GetVersionInfo) { - this.versionInfo = await wails.UpdateService.GetVersionInfo(); - } - } catch (err) { - console.error('Failed to load version info:', err); - } - } - - async checkForUpdates() { - this.isChecking = true; - this.checkResult = null; - - try { - const wails = (window as any).go?.main; - if (wails?.UpdateService?.CheckForUpdate) { - this.checkResult = await wails.UpdateService.CheckForUpdate(); - } - } catch (err) { - console.error('Failed to check for updates:', err); - this.checkResult = { - available: false, - currentVersion: this.versionInfo?.version || 'unknown', - latestVersion: '', - error: 'Failed to check for updates', - checkedAt: new Date().toISOString() - }; - } finally { - this.isChecking = false; - } - } - - async installUpdate() { - if (!this.checkResult?.available || !this.checkResult.release) { - return; - } - - this.isInstalling = true; - - try { - const wails = (window as any).go?.main; - if (wails?.UpdateService?.InstallUpdate) { - await wails.UpdateService.InstallUpdate(); - } - } catch (err) { - console.error('Failed to install update:', err); - alert('Failed to install update. Please try again or download manually.'); - } finally { - this.isInstalling = false; - } - } - - async onSettingsChange() { - // Debounce save - if (this.saveTimeout) { - clearTimeout(this.saveTimeout); - } - - this.saveTimeout = setTimeout(() => this.saveSettings(), 500); - } - - async saveSettings() { - try { - const wails = (window as any).go?.main; - if (wails?.UpdateService?.SetSettings) { - await wails.UpdateService.SetSettings(this.settings); - } else if (wails?.ConfigService?.SetUpdateSettings) { - await wails.ConfigService.SetUpdateSettings(this.settings); - } - this.saveMessage = 'Settings saved'; - this.saveError = false; - } catch (err) { - console.error('Failed to save update settings:', err); - this.saveMessage = 'Failed to save settings'; - this.saveError = true; - } - - // Clear message after 2 seconds - setTimeout(() => { - this.saveMessage = ''; - }, 2000); - } -} diff --git a/cmd/bugseti/frontend/src/app/tray/tray.component.ts b/cmd/bugseti/frontend/src/app/tray/tray.component.ts deleted file mode 100644 index f6232e90..00000000 --- a/cmd/bugseti/frontend/src/app/tray/tray.component.ts +++ /dev/null @@ -1,303 +0,0 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; -import { CommonModule } from '@angular/common'; - -interface TrayStatus { - running: boolean; - currentIssue: string; - queueSize: number; - issuesFixed: number; - prsMerged: number; -} - -@Component({ - selector: 'app-tray', - standalone: true, - imports: [CommonModule], - template: ` -
-
- - - {{ status.running ? 'Running' : 'Paused' }} - -
- -
-
- {{ status.queueSize }} - In Queue -
-
- {{ status.issuesFixed }} - Fixed -
-
- {{ status.prsMerged }} - Merged -
-
- -
-

Current Issue

-
-

{{ status.currentIssue }}

-
- - -
-
-
- -
-
- [ ] -

No issue in progress

- -
-
- -
- - - -
-
- `, - styles: [` - .tray-panel { - display: flex; - flex-direction: column; - height: 100%; - padding: var(--spacing-md); - background-color: var(--bg-primary); - } - - .tray-header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--spacing-md); - } - - .logo { - display: flex; - align-items: center; - gap: var(--spacing-sm); - } - - .logo-icon { - width: 28px; - height: 28px; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, var(--accent-primary), var(--accent-success)); - border-radius: var(--radius-md); - font-weight: bold; - color: white; - } - - .logo-text { - font-weight: 600; - font-size: 16px; - } - - .stats-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: var(--spacing-sm); - margin-bottom: var(--spacing-md); - } - - .stat-card { - display: flex; - flex-direction: column; - align-items: center; - padding: var(--spacing-sm); - background-color: var(--bg-secondary); - border-radius: var(--radius-md); - } - - .stat-value { - font-size: 24px; - font-weight: bold; - color: var(--accent-primary); - } - - .stat-label { - font-size: 11px; - color: var(--text-muted); - text-transform: uppercase; - } - - .current-issue { - flex: 1; - margin-bottom: var(--spacing-md); - } - - .current-issue h3 { - font-size: 12px; - color: var(--text-muted); - text-transform: uppercase; - margin-bottom: var(--spacing-sm); - } - - .issue-card { - background-color: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - padding: var(--spacing-md); - } - - .issue-title { - font-size: 13px; - line-height: 1.4; - margin-bottom: var(--spacing-sm); - } - - .issue-actions { - display: flex; - gap: var(--spacing-sm); - } - - .empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: var(--spacing-xl); - text-align: center; - } - - .empty-icon { - font-size: 32px; - color: var(--text-muted); - margin-bottom: var(--spacing-sm); - } - - .empty-state p { - color: var(--text-muted); - margin-bottom: var(--spacing-md); - } - - .tray-footer { - display: flex; - gap: var(--spacing-sm); - justify-content: center; - } - - .btn--sm { - padding: var(--spacing-xs) var(--spacing-sm); - font-size: 12px; - } - `] -}) -export class TrayComponent implements OnInit, OnDestroy { - status: TrayStatus = { - running: false, - currentIssue: '', - queueSize: 0, - issuesFixed: 0, - prsMerged: 0 - }; - - private refreshInterval?: ReturnType; - - ngOnInit() { - this.loadStatus(); - this.refreshInterval = setInterval(() => this.loadStatus(), 5000); - } - - ngOnDestroy() { - if (this.refreshInterval) { - clearInterval(this.refreshInterval); - } - } - - async loadStatus() { - try { - // Call Wails binding when available - if ((window as any).go?.main?.TrayService?.GetStatus) { - this.status = await (window as any).go.main.TrayService.GetStatus(); - } - } catch (err) { - console.error('Failed to load status:', err); - } - } - - async toggleRunning() { - try { - if (this.status.running) { - if ((window as any).go?.main?.TrayService?.PauseFetching) { - await (window as any).go.main.TrayService.PauseFetching(); - } - } else { - if ((window as any).go?.main?.TrayService?.StartFetching) { - await (window as any).go.main.TrayService.StartFetching(); - } - } - this.loadStatus(); - } catch (err) { - console.error('Failed to toggle running:', err); - } - } - - async nextIssue() { - try { - if ((window as any).go?.main?.TrayService?.NextIssue) { - await (window as any).go.main.TrayService.NextIssue(); - } - this.loadStatus(); - } catch (err) { - console.error('Failed to get next issue:', err); - } - } - - async skipIssue() { - try { - if ((window as any).go?.main?.TrayService?.SkipIssue) { - await (window as any).go.main.TrayService.SkipIssue(); - } - this.loadStatus(); - } catch (err) { - console.error('Failed to skip issue:', err); - } - } - - openWorkbench() { - if ((window as any).wails?.Window) { - (window as any).wails.Window.GetByName('workbench').then((w: any) => { - w.Show(); - w.Focus(); - }); - } - } - - openSettings() { - if ((window as any).wails?.Window) { - (window as any).wails.Window.GetByName('settings').then((w: any) => { - w.Show(); - w.Focus(); - }); - } - } - - openJellyfin() { - window.location.assign('/jellyfin'); - } -} diff --git a/cmd/bugseti/frontend/src/app/workbench/workbench.component.ts b/cmd/bugseti/frontend/src/app/workbench/workbench.component.ts deleted file mode 100644 index c8d4014d..00000000 --- a/cmd/bugseti/frontend/src/app/workbench/workbench.component.ts +++ /dev/null @@ -1,356 +0,0 @@ -import { Component, OnInit } from '@angular/core'; -import { CommonModule } from '@angular/common'; -import { FormsModule } from '@angular/forms'; - -interface Issue { - id: string; - number: number; - repo: string; - title: string; - body: string; - url: string; - labels: string[]; - author: string; - context?: IssueContext; -} - -interface IssueContext { - summary: string; - relevantFiles: string[]; - suggestedFix: string; - complexity: string; - estimatedTime: string; -} - -@Component({ - selector: 'app-workbench', - standalone: true, - imports: [CommonModule, FormsModule], - template: ` -
-
-

BugSETI Workbench

-
- - -
-
- -
- - -
-
-
-

PR Details

-
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
- -
-

No Issue Selected

-

Get an issue from the queue to start working.

- -
-
- `, - styles: [` - .workbench { - display: flex; - flex-direction: column; - height: 100%; - background-color: var(--bg-secondary); - } - - .workbench-header { - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--spacing-md) var(--spacing-lg); - background-color: var(--bg-primary); - border-bottom: 1px solid var(--border-color); - } - - .workbench-header h1 { - font-size: 18px; - margin: 0; - } - - .header-actions { - display: flex; - gap: var(--spacing-sm); - } - - .workbench-content { - display: grid; - grid-template-columns: 400px 1fr; - flex: 1; - overflow: hidden; - } - - .issue-panel { - display: flex; - flex-direction: column; - gap: var(--spacing-md); - padding: var(--spacing-md); - overflow-y: auto; - border-right: 1px solid var(--border-color); - } - - .editor-panel { - padding: var(--spacing-md); - overflow-y: auto; - } - - .labels { - display: flex; - flex-wrap: wrap; - gap: var(--spacing-xs); - margin: var(--spacing-sm) 0; - } - - .issue-meta { - display: flex; - gap: var(--spacing-md); - font-size: 12px; - color: var(--text-muted); - margin-bottom: var(--spacing-md); - } - - .issue-body { - padding: var(--spacing-md); - background-color: var(--bg-tertiary); - border-radius: var(--radius-md); - max-height: 200px; - overflow-y: auto; - } - - .issue-body pre { - white-space: pre-wrap; - word-wrap: break-word; - font-size: 13px; - line-height: 1.5; - margin: 0; - } - - .context-summary { - color: var(--text-secondary); - margin-bottom: var(--spacing-md); - } - - .context-section { - margin-bottom: var(--spacing-md); - } - - .context-section h4 { - font-size: 12px; - text-transform: uppercase; - color: var(--text-muted); - margin-bottom: var(--spacing-xs); - } - - .file-list { - list-style: none; - padding: 0; - margin: 0; - } - - .file-list li { - padding: var(--spacing-xs) 0; - } - - .context-meta { - font-size: 12px; - color: var(--text-muted); - } - - .empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - flex: 1; - text-align: center; - } - - .empty-state h2 { - color: var(--text-secondary); - } - - .empty-state p { - color: var(--text-muted); - } - `] -}) -export class WorkbenchComponent implements OnInit { - currentIssue: Issue | null = null; - prTitle = ''; - prBody = ''; - branchName = ''; - commitMessage = ''; - - get canSubmit(): boolean { - return !!this.currentIssue && !!this.prTitle; - } - - ngOnInit() { - this.loadCurrentIssue(); - } - - async loadCurrentIssue() { - try { - if ((window as any).go?.main?.TrayService?.GetCurrentIssue) { - this.currentIssue = await (window as any).go.main.TrayService.GetCurrentIssue(); - if (this.currentIssue) { - this.initDefaults(); - } - } - } catch (err) { - console.error('Failed to load current issue:', err); - } - } - - initDefaults() { - if (!this.currentIssue) return; - - this.prTitle = `Fix #${this.currentIssue.number}: ${this.currentIssue.title}`; - this.branchName = `bugseti/issue-${this.currentIssue.number}`; - this.commitMessage = `fix: resolve issue #${this.currentIssue.number}\n\n${this.currentIssue.title}`; - } - - async nextIssue() { - try { - if ((window as any).go?.main?.TrayService?.NextIssue) { - this.currentIssue = await (window as any).go.main.TrayService.NextIssue(); - if (this.currentIssue) { - this.initDefaults(); - } - } - } catch (err) { - console.error('Failed to get next issue:', err); - } - } - - async skipIssue() { - try { - if ((window as any).go?.main?.TrayService?.SkipIssue) { - await (window as any).go.main.TrayService.SkipIssue(); - this.currentIssue = null; - this.prTitle = ''; - this.prBody = ''; - this.branchName = ''; - this.commitMessage = ''; - } - } catch (err) { - console.error('Failed to skip issue:', err); - } - } - - async submitPR() { - if (!this.currentIssue || !this.canSubmit) return; - - try { - if ((window as any).go?.main?.SubmitService?.Submit) { - const result = await (window as any).go.main.SubmitService.Submit({ - issue: this.currentIssue, - title: this.prTitle, - body: this.prBody, - branch: this.branchName, - commitMsg: this.commitMessage - }); - - if (result.success) { - alert(`PR submitted successfully!\n\n${result.prUrl}`); - this.currentIssue = null; - } else { - alert(`Failed to submit PR: ${result.error}`); - } - } - } catch (err) { - console.error('Failed to submit PR:', err); - alert('Failed to submit PR. Check console for details.'); - } - } -} diff --git a/cmd/bugseti/frontend/src/favicon.ico b/cmd/bugseti/frontend/src/favicon.ico deleted file mode 100644 index e69de29b..00000000 diff --git a/cmd/bugseti/frontend/src/index.html b/cmd/bugseti/frontend/src/index.html deleted file mode 100644 index c05ac318..00000000 --- a/cmd/bugseti/frontend/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - BugSETI - - - - - - - - diff --git a/cmd/bugseti/frontend/src/main.ts b/cmd/bugseti/frontend/src/main.ts deleted file mode 100644 index 35b00f34..00000000 --- a/cmd/bugseti/frontend/src/main.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { AppComponent } from './app/app.component'; - -bootstrapApplication(AppComponent, appConfig) - .catch((err) => console.error(err)); diff --git a/cmd/bugseti/frontend/src/styles.scss b/cmd/bugseti/frontend/src/styles.scss deleted file mode 100644 index e28d79c3..00000000 --- a/cmd/bugseti/frontend/src/styles.scss +++ /dev/null @@ -1,268 +0,0 @@ -// BugSETI Global Styles - -// CSS Variables for theming -:root { - // Dark theme (default) - --bg-primary: #161b22; - --bg-secondary: #0d1117; - --bg-tertiary: #21262d; - --text-primary: #c9d1d9; - --text-secondary: #8b949e; - --text-muted: #6e7681; - --border-color: #30363d; - --accent-primary: #58a6ff; - --accent-success: #3fb950; - --accent-warning: #d29922; - --accent-danger: #f85149; - - // Spacing - --spacing-xs: 4px; - --spacing-sm: 8px; - --spacing-md: 16px; - --spacing-lg: 24px; - --spacing-xl: 32px; - - // Border radius - --radius-sm: 4px; - --radius-md: 6px; - --radius-lg: 12px; - - // Font - --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; - --font-mono: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace; -} - -// Light theme -[data-theme="light"] { - --bg-primary: #ffffff; - --bg-secondary: #f6f8fa; - --bg-tertiary: #f0f3f6; - --text-primary: #24292f; - --text-secondary: #57606a; - --text-muted: #8b949e; - --border-color: #d0d7de; - --accent-primary: #0969da; - --accent-success: #1a7f37; - --accent-warning: #9a6700; - --accent-danger: #cf222e; -} - -// Reset -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -html, body { - height: 100%; - width: 100%; -} - -body { - font-family: var(--font-family); - font-size: 14px; - line-height: 1.5; - color: var(--text-primary); - background-color: var(--bg-primary); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -// Typography -h1, h2, h3, h4, h5, h6 { - font-weight: 600; - line-height: 1.25; - margin-bottom: var(--spacing-sm); -} - -h1 { font-size: 24px; } -h2 { font-size: 20px; } -h3 { font-size: 16px; } -h4 { font-size: 14px; } - -p { - margin-bottom: var(--spacing-md); -} - -a { - color: var(--accent-primary); - text-decoration: none; - - &:hover { - text-decoration: underline; - } -} - -code { - font-family: var(--font-mono); - font-size: 12px; - padding: 2px 6px; - background-color: var(--bg-tertiary); - border-radius: var(--radius-sm); -} - -// Buttons -.btn { - display: inline-flex; - align-items: center; - justify-content: center; - gap: var(--spacing-xs); - padding: var(--spacing-sm) var(--spacing-md); - font-size: 14px; - font-weight: 500; - line-height: 1; - border: 1px solid transparent; - border-radius: var(--radius-md); - cursor: pointer; - transition: all 0.2s; - - &:disabled { - opacity: 0.5; - cursor: not-allowed; - } - - &--primary { - background-color: var(--accent-primary); - color: white; - - &:hover:not(:disabled) { - opacity: 0.9; - } - } - - &--secondary { - background-color: var(--bg-tertiary); - border-color: var(--border-color); - color: var(--text-primary); - - &:hover:not(:disabled) { - background-color: var(--bg-secondary); - } - } - - &--success { - background-color: var(--accent-success); - color: white; - } - - &--danger { - background-color: var(--accent-danger); - color: white; - } -} - -// Forms -.form-group { - margin-bottom: var(--spacing-md); -} - -.form-label { - display: block; - margin-bottom: var(--spacing-xs); - font-weight: 500; - color: var(--text-primary); -} - -.form-input, -.form-select, -.form-textarea { - width: 100%; - padding: var(--spacing-sm) var(--spacing-md); - font-size: 14px; - background-color: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-md); - color: var(--text-primary); - - &:focus { - outline: none; - border-color: var(--accent-primary); - box-shadow: 0 0 0 3px rgba(88, 166, 255, 0.2); - } - - &::placeholder { - color: var(--text-muted); - } -} - -.form-textarea { - resize: vertical; - min-height: 100px; -} - -// Cards -.card { - background-color: var(--bg-secondary); - border: 1px solid var(--border-color); - border-radius: var(--radius-lg); - padding: var(--spacing-md); - - &__header { - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: var(--spacing-md); - padding-bottom: var(--spacing-sm); - border-bottom: 1px solid var(--border-color); - } - - &__title { - font-size: 16px; - font-weight: 600; - } -} - -// Badges -.badge { - display: inline-flex; - align-items: center; - padding: 2px 8px; - font-size: 12px; - font-weight: 500; - border-radius: 999px; - - &--primary { - background-color: rgba(88, 166, 255, 0.15); - color: var(--accent-primary); - } - - &--success { - background-color: rgba(63, 185, 80, 0.15); - color: var(--accent-success); - } - - &--warning { - background-color: rgba(210, 153, 34, 0.15); - color: var(--accent-warning); - } - - &--danger { - background-color: rgba(248, 81, 73, 0.15); - color: var(--accent-danger); - } -} - -// Utility classes -.text-center { text-align: center; } -.text-right { text-align: right; } -.text-muted { color: var(--text-muted); } -.text-success { color: var(--accent-success); } -.text-danger { color: var(--accent-danger); } -.text-warning { color: var(--accent-warning); } - -.flex { display: flex; } -.flex-col { flex-direction: column; } -.items-center { align-items: center; } -.justify-between { justify-content: space-between; } -.gap-sm { gap: var(--spacing-sm); } -.gap-md { gap: var(--spacing-md); } - -.mt-sm { margin-top: var(--spacing-sm); } -.mt-md { margin-top: var(--spacing-md); } -.mb-sm { margin-bottom: var(--spacing-sm); } -.mb-md { margin-bottom: var(--spacing-md); } - -.hidden { display: none; } diff --git a/cmd/bugseti/frontend/tsconfig.app.json b/cmd/bugseti/frontend/tsconfig.app.json deleted file mode 100644 index 7d7c716d..00000000 --- a/cmd/bugseti/frontend/tsconfig.app.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": [ - "src/main.ts" - ], - "include": [ - "src/**/*.d.ts" - ] -} diff --git a/cmd/bugseti/frontend/tsconfig.json b/cmd/bugseti/frontend/tsconfig.json deleted file mode 100644 index 62eaf438..00000000 --- a/cmd/bugseti/frontend/tsconfig.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "compileOnSave": false, - "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "bundler", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "lib": [ - "ES2022", - "dom" - ], - "paths": { - "@app/*": ["src/app/*"], - "@shared/*": ["src/app/shared/*"] - } - }, - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/cmd/bugseti/frontend/tsconfig.spec.json b/cmd/bugseti/frontend/tsconfig.spec.json deleted file mode 100644 index b18619fd..00000000 --- a/cmd/bugseti/frontend/tsconfig.spec.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": [ - "jasmine" - ] - }, - "include": [ - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/cmd/bugseti/go.mod b/cmd/bugseti/go.mod deleted file mode 100644 index 7bdc52fc..00000000 --- a/cmd/bugseti/go.mod +++ /dev/null @@ -1,88 +0,0 @@ -module forge.lthn.ai/core/go/cmd/bugseti - -go 1.25.5 - -require ( - forge.lthn.ai/core/go v0.0.0 - forge.lthn.ai/core/go/internal/bugseti v0.0.0 - forge.lthn.ai/core/go/internal/bugseti/updater v0.0.0 - github.com/Snider/Borg v0.2.0 - forge.lthn.ai/core/go v0.0.0 - forge.lthn.ai/core/go/internal/bugseti v0.0.0 - forge.lthn.ai/core/go/internal/bugseti/updater v0.0.0 - github.com/wailsapp/wails/v3 v3.0.0-alpha.64 -) - -replace forge.lthn.ai/core/go => ../.. - -replace forge.lthn.ai/core/go/internal/bugseti => ../../internal/bugseti - -replace forge.lthn.ai/core/go/internal/bugseti/updater => ../../internal/bugseti/updater - -require ( - codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 // indirect - dario.cat/mergo v1.0.2 // indirect - github.com/42wim/httpsig v1.2.3 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/Snider/Enchantrix v0.0.2 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/buger/jsonparser v1.1.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/davidmz/go-pageant v1.0.2 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-fed/httpsig v1.1.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect - github.com/invopop/jsonschema v0.13.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mailru/easyjson v0.9.1 // indirect - github.com/mark3labs/mcp-go v0.43.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect - github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect - github.com/spf13/viper v1.21.0 // indirect - github.com/subosito/gotenv v1.6.0 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/mod v0.32.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/cmd/bugseti/go.sum b/cmd/bugseti/go.sum deleted file mode 100644 index 479e6650..00000000 --- a/cmd/bugseti/go.sum +++ /dev/null @@ -1,181 +0,0 @@ -codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 h1:HTCWpzyWQOHDWt3LzI6/d2jvUDsw/vgGRWm/8BTvcqI= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/Snider/Borg v0.2.0 h1:iCyDhY4WTXi39+FexRwXbn2YpZ2U9FUXVXDZk9xRCXQ= -github.com/Snider/Borg v0.2.0/go.mod h1:TqlKnfRo9okioHbgrZPfWjQsztBV0Nfskz4Om1/vdMY= -github.com/Snider/Enchantrix v0.0.2 h1:ExZQiBhfS/p/AHFTKhY80TOd+BXZjK95EzByAEgwvjs= -github.com/Snider/Enchantrix v0.0.2/go.mod h1:CtFcLAvnDT1KcuF1JBb/DJj0KplY8jHryO06KzQ1hsQ= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8= -github.com/mark3labs/mcp-go v0.43.2 h1:21PUSlWWiSbUPQwXIJ5WKlETixpFpq+WBpbMGDSVy/I= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= -github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/wailsapp/wails/v3 v3.0.0-alpha.64 h1:xAhLFVfdbg7XdZQ5mMQmBv2BglWu8hMqe50Z+3UJvBs= -github.com/wailsapp/wails/v3 v3.0.0-alpha.64/go.mod h1:zvgNL/mlFcX8aRGu6KOz9AHrMmTBD+4hJRQIONqF/Yw= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/cmd/bugseti/icons/appicon.png b/cmd/bugseti/icons/appicon.png deleted file mode 100644 index 5131e1cd..00000000 Binary files a/cmd/bugseti/icons/appicon.png and /dev/null differ diff --git a/cmd/bugseti/icons/icons.go b/cmd/bugseti/icons/icons.go deleted file mode 100644 index 083f6b38..00000000 --- a/cmd/bugseti/icons/icons.go +++ /dev/null @@ -1,25 +0,0 @@ -// Package icons provides embedded icon assets for the BugSETI application. -package icons - -import _ "embed" - -// TrayTemplate is the template icon for macOS systray (22x22 PNG, black on transparent). -// Template icons automatically adapt to light/dark mode on macOS. -// -//go:embed tray-template.png -var TrayTemplate []byte - -// TrayLight is the light mode icon for Windows/Linux systray. -// -//go:embed tray-light.png -var TrayLight []byte - -// TrayDark is the dark mode icon for Windows/Linux systray. -// -//go:embed tray-dark.png -var TrayDark []byte - -// AppIcon is the main application icon. -// -//go:embed appicon.png -var AppIcon []byte diff --git a/cmd/bugseti/icons/tray-dark.png b/cmd/bugseti/icons/tray-dark.png deleted file mode 100644 index e8295b79..00000000 Binary files a/cmd/bugseti/icons/tray-dark.png and /dev/null differ diff --git a/cmd/bugseti/icons/tray-light.png b/cmd/bugseti/icons/tray-light.png deleted file mode 100644 index e4457ce6..00000000 Binary files a/cmd/bugseti/icons/tray-light.png and /dev/null differ diff --git a/cmd/bugseti/icons/tray-template.png b/cmd/bugseti/icons/tray-template.png deleted file mode 100644 index f6c03ff8..00000000 Binary files a/cmd/bugseti/icons/tray-template.png and /dev/null differ diff --git a/cmd/bugseti/main.go b/cmd/bugseti/main.go deleted file mode 100644 index 3f4777dd..00000000 --- a/cmd/bugseti/main.go +++ /dev/null @@ -1,290 +0,0 @@ -// Package main provides the BugSETI system tray application. -// BugSETI - "Distributed Bug Fixing like SETI@home but for code" -// -// The application runs as a system tray app that: -// - Pulls OSS issues from Forgejo -// - Uses AI to prepare context for each issue -// - Presents issues to users for fixing -// - Automates PR submission -package main - -import ( - "embed" - "io/fs" - "log" - "net/http" - "runtime" - "strings" - - "forge.lthn.ai/core/go/cmd/bugseti/icons" - "forge.lthn.ai/core/cli/internal/bugseti" - "forge.lthn.ai/core/cli/internal/bugseti/updater" - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -//go:embed all:frontend/dist/bugseti/browser -var assets embed.FS - -func main() { - // Strip the embed path prefix so files are served from root - staticAssets, err := fs.Sub(assets, "frontend/dist/bugseti/browser") - if err != nil { - log.Fatal(err) - } - - // Initialize the config service - configService := bugseti.NewConfigService() - if err := configService.Load(); err != nil { - log.Printf("Warning: Could not load config: %v", err) - } - - // Check Forgejo API availability - forgeClient, err := bugseti.CheckForge() - if err != nil { - log.Fatalf("Forgejo check failed: %v\n\nConfigure with: core forge config --url URL --token TOKEN", err) - } - - // Initialize core services - notifyService := bugseti.NewNotifyService(configService) - statsService := bugseti.NewStatsService(configService) - fetcherService := bugseti.NewFetcherService(configService, notifyService, forgeClient) - queueService := bugseti.NewQueueService(configService) - seederService := bugseti.NewSeederService(configService, forgeClient.URL(), forgeClient.Token()) - submitService := bugseti.NewSubmitService(configService, notifyService, statsService, forgeClient) - hubService := bugseti.NewHubService(configService) - versionService := bugseti.NewVersionService() - workspaceService := NewWorkspaceService(configService) - - // Initialize update service - updateService, err := updater.NewService(configService) - if err != nil { - log.Printf("Warning: Could not initialize update service: %v", err) - } - - // Create the tray service (we'll set the app reference later) - trayService := NewTrayService(nil) - - // Build services list - services := []application.Service{ - application.NewService(configService), - application.NewService(notifyService), - application.NewService(statsService), - application.NewService(fetcherService), - application.NewService(queueService), - application.NewService(seederService), - application.NewService(submitService), - application.NewService(versionService), - application.NewService(workspaceService), - application.NewService(hubService), - application.NewService(trayService), - } - - // Add update service if available - if updateService != nil { - services = append(services, application.NewService(updateService)) - } - - // Create the application - app := application.New(application.Options{ - Name: "BugSETI", - Description: "Distributed Bug Fixing - like SETI@home but for code", - Services: services, - Assets: application.AssetOptions{ - Handler: spaHandler(staticAssets), - }, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - // Set the app reference and services in tray service - trayService.app = app - trayService.SetServices(fetcherService, queueService, configService, statsService) - - // Set up system tray - setupSystemTray(app, fetcherService, queueService, configService) - - // Start update service background checker - if updateService != nil { - updateService.Start() - } - - log.Println("Starting BugSETI...") - log.Println(" - System tray active") - log.Println(" - Waiting for issues...") - log.Printf(" - Version: %s (%s)", bugseti.GetVersion(), bugseti.GetChannel()) - - // Attempt hub registration (non-blocking) - if hubURL := configService.GetHubURL(); hubURL != "" { - if err := hubService.AutoRegister(); err != nil { - log.Printf(" - Hub: auto-register skipped: %v", err) - } else if err := hubService.Register(); err != nil { - log.Printf(" - Hub: registration failed: %v", err) - } else { - log.Println(" - Hub: registered with portal") - } - } else { - log.Println(" - Hub: not configured (set hubUrl in config)") - } - - if err := app.Run(); err != nil { - log.Fatal(err) - } - - // Stop update service on exit - if updateService != nil { - updateService.Stop() - } -} - -// setupSystemTray configures the system tray icon and menu -func setupSystemTray(app *application.App, fetcher *bugseti.FetcherService, queue *bugseti.QueueService, config *bugseti.ConfigService) { - systray := app.SystemTray.New() - systray.SetTooltip("BugSETI - Distributed Bug Fixing") - - // Set tray icon based on OS - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.TrayTemplate) - } else { - systray.SetDarkModeIcon(icons.TrayDark) - systray.SetIcon(icons.TrayLight) - } - - // Create tray panel window (workbench preview) - trayWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "tray-panel", - Title: "BugSETI", - Width: 420, - Height: 520, - URL: "/tray", - Hidden: true, - Frameless: true, - BackgroundColour: application.NewRGB(22, 27, 34), - }) - systray.AttachWindow(trayWindow).WindowOffset(5) - - // Create main workbench window - workbenchWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "workbench", - Title: "BugSETI Workbench", - Width: 1200, - Height: 800, - URL: "/workbench", - Hidden: true, - BackgroundColour: application.NewRGB(22, 27, 34), - }) - - // Create settings window - settingsWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "BugSETI Settings", - Width: 600, - Height: 500, - URL: "/settings", - Hidden: true, - BackgroundColour: application.NewRGB(22, 27, 34), - }) - - // Create onboarding window - onboardingWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "onboarding", - Title: "Welcome to BugSETI", - Width: 700, - Height: 600, - URL: "/onboarding", - Hidden: true, - BackgroundColour: application.NewRGB(22, 27, 34), - }) - - // Build tray menu - trayMenu := app.Menu.New() - - // Status item (dynamic) - statusItem := trayMenu.Add("Status: Idle") - statusItem.SetEnabled(false) - - trayMenu.AddSeparator() - - // Start/Pause toggle - startPauseItem := trayMenu.Add("Start Fetching") - startPauseItem.OnClick(func(ctx *application.Context) { - if fetcher.IsRunning() { - fetcher.Pause() - startPauseItem.SetLabel("Start Fetching") - statusItem.SetLabel("Status: Paused") - } else { - fetcher.Start() - startPauseItem.SetLabel("Pause") - statusItem.SetLabel("Status: Running") - } - }) - - trayMenu.AddSeparator() - - // Current Issue - currentIssueItem := trayMenu.Add("Current Issue: None") - currentIssueItem.OnClick(func(ctx *application.Context) { - if issue := queue.CurrentIssue(); issue != nil { - workbenchWindow.Show() - workbenchWindow.Focus() - } - }) - - // Open Workbench - trayMenu.Add("Open Workbench").OnClick(func(ctx *application.Context) { - workbenchWindow.Show() - workbenchWindow.Focus() - }) - - trayMenu.AddSeparator() - - // Settings - trayMenu.Add("Settings...").OnClick(func(ctx *application.Context) { - settingsWindow.Show() - settingsWindow.Focus() - }) - - // Stats submenu - statsMenu := trayMenu.AddSubmenu("Stats") - statsMenu.Add("Issues Fixed: 0").SetEnabled(false) - statsMenu.Add("PRs Merged: 0").SetEnabled(false) - statsMenu.Add("Repos Contributed: 0").SetEnabled(false) - - trayMenu.AddSeparator() - - // Quit - trayMenu.Add("Quit BugSETI").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - systray.SetMenu(trayMenu) - - // Check if onboarding needed (deferred until app is running) - app.Event.RegisterApplicationEventHook(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) { - if !config.IsOnboarded() { - onboardingWindow.Show() - onboardingWindow.Focus() - } - }) -} - -// spaHandler wraps an fs.FS to serve static files with SPA fallback. -// If the requested path doesn't match a real file, it serves index.html -// so Angular's client-side router can handle the route. -func spaHandler(fsys fs.FS) http.Handler { - fileServer := http.FileServer(http.FS(fsys)) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - path := strings.TrimPrefix(r.URL.Path, "/") - if path == "" { - path = "index.html" - } - - // Check if the file exists - if _, err := fs.Stat(fsys, path); err != nil { - // File doesn't exist — serve index.html for SPA routing - r.URL.Path = "/" - } - fileServer.ServeHTTP(w, r) - }) -} diff --git a/cmd/bugseti/tray.go b/cmd/bugseti/tray.go deleted file mode 100644 index 3610fecc..00000000 --- a/cmd/bugseti/tray.go +++ /dev/null @@ -1,158 +0,0 @@ -// Package main provides the BugSETI system tray application. -package main - -import ( - "context" - "log" - - "forge.lthn.ai/core/cli/internal/bugseti" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// TrayService provides system tray bindings for the frontend. -type TrayService struct { - app *application.App - fetcher *bugseti.FetcherService - queue *bugseti.QueueService - config *bugseti.ConfigService - stats *bugseti.StatsService -} - -// NewTrayService creates a new TrayService instance. -func NewTrayService(app *application.App) *TrayService { - return &TrayService{ - app: app, - } -} - -// SetServices sets the service references after initialization. -func (t *TrayService) SetServices(fetcher *bugseti.FetcherService, queue *bugseti.QueueService, config *bugseti.ConfigService, stats *bugseti.StatsService) { - t.fetcher = fetcher - t.queue = queue - t.config = config - t.stats = stats -} - -// ServiceName returns the service name for Wails. -func (t *TrayService) ServiceName() string { - return "TrayService" -} - -// ServiceStartup is called when the Wails application starts. -func (t *TrayService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - log.Println("TrayService started") - return nil -} - -// ServiceShutdown is called when the Wails application shuts down. -func (t *TrayService) ServiceShutdown() error { - log.Println("TrayService shutdown") - return nil -} - -// TrayStatus represents the current status of the tray. -type TrayStatus struct { - Running bool `json:"running"` - CurrentIssue string `json:"currentIssue"` - QueueSize int `json:"queueSize"` - IssuesFixed int `json:"issuesFixed"` - PRsMerged int `json:"prsMerged"` -} - -// GetStatus returns the current tray status. -func (t *TrayService) GetStatus() TrayStatus { - var currentIssue string - if t.queue != nil { - if issue := t.queue.CurrentIssue(); issue != nil { - currentIssue = issue.Title - } - } - - var queueSize int - if t.queue != nil { - queueSize = t.queue.Size() - } - - var running bool - if t.fetcher != nil { - running = t.fetcher.IsRunning() - } - - var issuesFixed, prsMerged int - if t.stats != nil { - stats := t.stats.GetStats() - issuesFixed = stats.IssuesAttempted - prsMerged = stats.PRsMerged - } - - return TrayStatus{ - Running: running, - CurrentIssue: currentIssue, - QueueSize: queueSize, - IssuesFixed: issuesFixed, - PRsMerged: prsMerged, - } -} - -// StartFetching starts the issue fetcher. -func (t *TrayService) StartFetching() error { - if t.fetcher == nil { - return nil - } - return t.fetcher.Start() -} - -// PauseFetching pauses the issue fetcher. -func (t *TrayService) PauseFetching() { - if t.fetcher != nil { - t.fetcher.Pause() - } -} - -// GetCurrentIssue returns the current issue being worked on. -func (t *TrayService) GetCurrentIssue() *bugseti.Issue { - if t.queue == nil { - return nil - } - return t.queue.CurrentIssue() -} - -// NextIssue moves to the next issue in the queue. -func (t *TrayService) NextIssue() *bugseti.Issue { - if t.queue == nil { - return nil - } - return t.queue.Next() -} - -// SkipIssue skips the current issue. -func (t *TrayService) SkipIssue() { - if t.queue == nil { - return - } - t.queue.Skip() -} - -// ShowWindow shows a specific window by name. -func (t *TrayService) ShowWindow(name string) { - if t.app == nil { - return - } - // Window will be shown by the frontend via Wails runtime -} - -// IsOnboarded returns whether the user has completed onboarding. -func (t *TrayService) IsOnboarded() bool { - if t.config == nil { - return false - } - return t.config.IsOnboarded() -} - -// CompleteOnboarding marks onboarding as complete. -func (t *TrayService) CompleteOnboarding() error { - if t.config == nil { - return nil - } - return t.config.CompleteOnboarding() -} diff --git a/cmd/bugseti/workspace.go b/cmd/bugseti/workspace.go deleted file mode 100644 index 69b53495..00000000 --- a/cmd/bugseti/workspace.go +++ /dev/null @@ -1,374 +0,0 @@ -// Package main provides the BugSETI system tray application. -package main - -import ( - "fmt" - "io/fs" - "log" - "os" - "path/filepath" - "sort" - "sync" - "time" - - "forge.lthn.ai/core/cli/internal/bugseti" - "forge.lthn.ai/core/go/pkg/io/datanode" - "github.com/Snider/Borg/pkg/tim" -) - -const ( - // defaultMaxWorkspaces is the fallback upper bound when config is unavailable. - defaultMaxWorkspaces = 100 - // defaultWorkspaceTTL is the fallback TTL when config is unavailable. - defaultWorkspaceTTL = 24 * time.Hour - // sweepInterval is how often the background sweeper runs. - sweepInterval = 5 * time.Minute -) - -// WorkspaceService manages DataNode-backed workspaces for issues. -// Each issue gets a sandboxed in-memory filesystem that can be -// snapshotted, packaged as a TIM container, or shipped as a crash report. -type WorkspaceService struct { - config *bugseti.ConfigService - workspaces map[string]*Workspace // issue ID -> workspace - mu sync.RWMutex - done chan struct{} // signals the background sweeper to stop - stopped chan struct{} // closed when the sweeper goroutine exits -} - -// Workspace tracks a DataNode-backed workspace for an issue. -type Workspace struct { - Issue *bugseti.Issue `json:"issue"` - Medium *datanode.Medium - DiskPath string `json:"diskPath"` - CreatedAt time.Time `json:"createdAt"` - Snapshots int `json:"snapshots"` -} - -// CrashReport contains a packaged workspace state for debugging. -type CrashReport struct { - IssueID string `json:"issueId"` - Repo string `json:"repo"` - Number int `json:"number"` - Title string `json:"title"` - Error string `json:"error"` - Timestamp time.Time `json:"timestamp"` - Data []byte `json:"data"` // tar snapshot - Files int `json:"files"` - Size int64 `json:"size"` -} - -// NewWorkspaceService creates a new WorkspaceService. -// Call Start() to begin the background TTL sweeper. -func NewWorkspaceService(config *bugseti.ConfigService) *WorkspaceService { - return &WorkspaceService{ - config: config, - workspaces: make(map[string]*Workspace), - done: make(chan struct{}), - stopped: make(chan struct{}), - } -} - -// ServiceName returns the service name for Wails. -func (w *WorkspaceService) ServiceName() string { - return "WorkspaceService" -} - -// Start launches the background sweeper goroutine that periodically -// evicts expired workspaces. This prevents unbounded map growth even -// when no new Capture calls arrive. -func (w *WorkspaceService) Start() { - go func() { - defer close(w.stopped) - ticker := time.NewTicker(sweepInterval) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - w.mu.Lock() - evicted := w.cleanup() - w.mu.Unlock() - if evicted > 0 { - log.Printf("Workspace sweeper: evicted %d stale entries, %d remaining", evicted, w.ActiveWorkspaces()) - } - case <-w.done: - return - } - } - }() - log.Printf("Workspace sweeper started (interval=%s, ttl=%s, max=%d)", - sweepInterval, w.ttl(), w.maxCap()) -} - -// Stop signals the background sweeper to exit and waits for it to finish. -func (w *WorkspaceService) Stop() { - close(w.done) - <-w.stopped - log.Printf("Workspace sweeper stopped") -} - -// ttl returns the configured workspace TTL, falling back to the default. -func (w *WorkspaceService) ttl() time.Duration { - if w.config != nil { - return w.config.GetWorkspaceTTL() - } - return defaultWorkspaceTTL -} - -// maxCap returns the configured max workspace count, falling back to the default. -func (w *WorkspaceService) maxCap() int { - if w.config != nil { - return w.config.GetMaxWorkspaces() - } - return defaultMaxWorkspaces -} - -// Capture loads a filesystem workspace into a DataNode Medium. -// Call this after git clone to create the in-memory snapshot. -func (w *WorkspaceService) Capture(issue *bugseti.Issue, diskPath string) error { - if issue == nil { - return fmt.Errorf("issue is nil") - } - - m := datanode.New() - - // Walk the filesystem and load all files into the DataNode - err := filepath.WalkDir(diskPath, func(path string, d fs.DirEntry, err error) error { - if err != nil { - return nil // skip errors - } - - // Get relative path - rel, err := filepath.Rel(diskPath, path) - if err != nil { - return nil - } - if rel == "." { - return nil - } - - // Skip .git internals (keep .git marker but not the pack files) - if rel == ".git" { - return fs.SkipDir - } - - if d.IsDir() { - return m.EnsureDir(rel) - } - - // Skip large files (>1MB) to keep DataNode lightweight - info, err := d.Info() - if err != nil || info.Size() > 1<<20 { - return nil - } - - content, err := os.ReadFile(path) - if err != nil { - return nil - } - return m.Write(rel, string(content)) - }) - if err != nil { - return fmt.Errorf("failed to capture workspace: %w", err) - } - - w.mu.Lock() - w.cleanup() - w.workspaces[issue.ID] = &Workspace{ - Issue: issue, - Medium: m, - DiskPath: diskPath, - CreatedAt: time.Now(), - } - w.mu.Unlock() - - log.Printf("Captured workspace for issue #%d (%s)", issue.Number, issue.Repo) - return nil -} - -// GetMedium returns the DataNode Medium for an issue's workspace. -func (w *WorkspaceService) GetMedium(issueID string) *datanode.Medium { - w.mu.RLock() - defer w.mu.RUnlock() - - ws := w.workspaces[issueID] - if ws == nil { - return nil - } - return ws.Medium -} - -// Snapshot takes a tar snapshot of the workspace. -func (w *WorkspaceService) Snapshot(issueID string) ([]byte, error) { - w.mu.Lock() - defer w.mu.Unlock() - - ws := w.workspaces[issueID] - if ws == nil { - return nil, fmt.Errorf("workspace not found: %s", issueID) - } - - data, err := ws.Medium.Snapshot() - if err != nil { - return nil, fmt.Errorf("snapshot failed: %w", err) - } - - ws.Snapshots++ - return data, nil -} - -// PackageCrashReport captures the current workspace state as a crash report. -// Re-reads from disk to get the latest state (including git changes). -func (w *WorkspaceService) PackageCrashReport(issue *bugseti.Issue, errMsg string) (*CrashReport, error) { - if issue == nil { - return nil, fmt.Errorf("issue is nil") - } - - w.mu.RLock() - ws := w.workspaces[issue.ID] - w.mu.RUnlock() - - var diskPath string - if ws != nil { - diskPath = ws.DiskPath - } else { - // Try to find the workspace on disk - baseDir := w.config.GetWorkspaceDir() - if baseDir == "" { - baseDir = filepath.Join(os.TempDir(), "bugseti") - } - diskPath = filepath.Join(baseDir, sanitizeForPath(issue.Repo), fmt.Sprintf("issue-%d", issue.Number)) - } - - // Re-capture from disk to get latest state - if err := w.Capture(issue, diskPath); err != nil { - return nil, fmt.Errorf("capture failed: %w", err) - } - - // Snapshot the captured workspace - data, err := w.Snapshot(issue.ID) - if err != nil { - return nil, fmt.Errorf("snapshot failed: %w", err) - } - - return &CrashReport{ - IssueID: issue.ID, - Repo: issue.Repo, - Number: issue.Number, - Title: issue.Title, - Error: errMsg, - Timestamp: time.Now(), - Data: data, - Size: int64(len(data)), - }, nil -} - -// PackageTIM wraps the workspace as a TIM container (runc-compatible bundle). -// The resulting TIM can be executed via runc or encrypted to .stim for transit. -func (w *WorkspaceService) PackageTIM(issueID string) (*tim.TerminalIsolationMatrix, error) { - w.mu.RLock() - ws := w.workspaces[issueID] - w.mu.RUnlock() - - if ws == nil { - return nil, fmt.Errorf("workspace not found: %s", issueID) - } - - dn := ws.Medium.DataNode() - return tim.FromDataNode(dn) -} - -// SaveCrashReport writes a crash report to the data directory. -func (w *WorkspaceService) SaveCrashReport(report *CrashReport) (string, error) { - dataDir := w.config.GetDataDir() - if dataDir == "" { - dataDir = filepath.Join(os.TempDir(), "bugseti") - } - - crashDir := filepath.Join(dataDir, "crash-reports") - if err := os.MkdirAll(crashDir, 0755); err != nil { - return "", fmt.Errorf("failed to create crash dir: %w", err) - } - - filename := fmt.Sprintf("crash-%s-issue-%d-%s.tar", - sanitizeForPath(report.Repo), - report.Number, - report.Timestamp.Format("20060102-150405"), - ) - path := filepath.Join(crashDir, filename) - - if err := os.WriteFile(path, report.Data, 0644); err != nil { - return "", fmt.Errorf("failed to write crash report: %w", err) - } - - log.Printf("Crash report saved: %s (%d bytes)", path, report.Size) - return path, nil -} - -// cleanup evicts expired workspaces and enforces the max size cap. -// Must be called with w.mu held for writing. -// Returns the number of evicted entries. -func (w *WorkspaceService) cleanup() int { - now := time.Now() - ttl := w.ttl() - cap := w.maxCap() - evicted := 0 - - // First pass: evict entries older than TTL. - for id, ws := range w.workspaces { - if now.Sub(ws.CreatedAt) > ttl { - delete(w.workspaces, id) - evicted++ - } - } - - // Second pass: if still over cap, evict oldest entries. - if len(w.workspaces) > cap { - type entry struct { - id string - createdAt time.Time - } - entries := make([]entry, 0, len(w.workspaces)) - for id, ws := range w.workspaces { - entries = append(entries, entry{id, ws.CreatedAt}) - } - sort.Slice(entries, func(i, j int) bool { - return entries[i].createdAt.Before(entries[j].createdAt) - }) - toEvict := len(w.workspaces) - cap - for i := 0; i < toEvict; i++ { - delete(w.workspaces, entries[i].id) - evicted++ - } - } - - return evicted -} - -// Release removes a workspace from memory. -func (w *WorkspaceService) Release(issueID string) { - w.mu.Lock() - delete(w.workspaces, issueID) - w.mu.Unlock() -} - -// ActiveWorkspaces returns the count of active workspaces. -func (w *WorkspaceService) ActiveWorkspaces() int { - w.mu.RLock() - defer w.mu.RUnlock() - return len(w.workspaces) -} - -// sanitizeForPath converts owner/repo to a safe directory name. -func sanitizeForPath(s string) string { - result := make([]byte, 0, len(s)) - for _, c := range s { - if c == '/' || c == '\\' || c == ':' { - result = append(result, '-') - } else { - result = append(result, byte(c)) - } - } - return string(result) -} diff --git a/cmd/bugseti/workspace_test.go b/cmd/bugseti/workspace_test.go deleted file mode 100644 index d1711216..00000000 --- a/cmd/bugseti/workspace_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package main - -import ( - "fmt" - "testing" - "time" - - "forge.lthn.ai/core/cli/internal/bugseti" -) - -func TestCleanup_TTL(t *testing.T) { - svc := NewWorkspaceService(bugseti.NewConfigService()) - - // Seed with entries that are older than TTL. - svc.mu.Lock() - for i := 0; i < 5; i++ { - svc.workspaces[fmt.Sprintf("old-%d", i)] = &Workspace{ - CreatedAt: time.Now().Add(-25 * time.Hour), - } - } - // Add one fresh entry. - svc.workspaces["fresh"] = &Workspace{ - CreatedAt: time.Now(), - } - svc.cleanup() - svc.mu.Unlock() - - if got := svc.ActiveWorkspaces(); got != 1 { - t.Errorf("expected 1 workspace after TTL cleanup, got %d", got) - } -} - -func TestCleanup_MaxSize(t *testing.T) { - svc := NewWorkspaceService(bugseti.NewConfigService()) - - maxCap := svc.maxCap() - - // Fill beyond the cap with fresh entries. - svc.mu.Lock() - for i := 0; i < maxCap+20; i++ { - svc.workspaces[fmt.Sprintf("ws-%d", i)] = &Workspace{ - CreatedAt: time.Now().Add(-time.Duration(i) * time.Minute), - } - } - svc.cleanup() - svc.mu.Unlock() - - if got := svc.ActiveWorkspaces(); got != maxCap { - t.Errorf("expected %d workspaces after cap cleanup, got %d", maxCap, got) - } -} - -func TestCleanup_EvictsOldestWhenOverCap(t *testing.T) { - svc := NewWorkspaceService(bugseti.NewConfigService()) - - maxCap := svc.maxCap() - - // Create maxCap+1 entries; the newest should survive. - svc.mu.Lock() - for i := 0; i <= maxCap; i++ { - svc.workspaces[fmt.Sprintf("ws-%d", i)] = &Workspace{ - CreatedAt: time.Now().Add(-time.Duration(maxCap-i) * time.Minute), - } - } - svc.cleanup() - svc.mu.Unlock() - - // The newest entry (ws-) should still exist. - newest := fmt.Sprintf("ws-%d", maxCap) - - svc.mu.RLock() - _, exists := svc.workspaces[newest] - svc.mu.RUnlock() - if !exists { - t.Error("expected newest workspace to survive eviction") - } - - // The oldest entry (ws-0) should have been evicted. - svc.mu.RLock() - _, exists = svc.workspaces["ws-0"] - svc.mu.RUnlock() - if exists { - t.Error("expected oldest workspace to be evicted") - } -} - -func TestCleanup_ReturnsEvictedCount(t *testing.T) { - svc := NewWorkspaceService(bugseti.NewConfigService()) - - svc.mu.Lock() - for i := 0; i < 3; i++ { - svc.workspaces[fmt.Sprintf("old-%d", i)] = &Workspace{ - CreatedAt: time.Now().Add(-25 * time.Hour), - } - } - svc.workspaces["fresh"] = &Workspace{ - CreatedAt: time.Now(), - } - evicted := svc.cleanup() - svc.mu.Unlock() - - if evicted != 3 { - t.Errorf("expected 3 evicted entries, got %d", evicted) - } -} - -func TestStartStop(t *testing.T) { - svc := NewWorkspaceService(bugseti.NewConfigService()) - svc.Start() - - // Add a stale entry while the sweeper is running. - svc.mu.Lock() - svc.workspaces["stale"] = &Workspace{ - CreatedAt: time.Now().Add(-25 * time.Hour), - } - svc.mu.Unlock() - - // Stop should return without hanging. - svc.Stop() -} - -func TestConfigurableTTL(t *testing.T) { - cfg := bugseti.NewConfigService() - svc := NewWorkspaceService(cfg) - - // Default TTL should be 24h (1440 minutes). - if got := svc.ttl(); got != 24*time.Hour { - t.Errorf("expected default TTL of 24h, got %s", got) - } - - // Default max cap should be 100. - if got := svc.maxCap(); got != 100 { - t.Errorf("expected default max cap of 100, got %d", got) - } -} - -func TestNilConfigFallback(t *testing.T) { - svc := &WorkspaceService{ - config: nil, - workspaces: make(map[string]*Workspace), - done: make(chan struct{}), - stopped: make(chan struct{}), - } - - if got := svc.ttl(); got != defaultWorkspaceTTL { - t.Errorf("expected fallback TTL %s, got %s", defaultWorkspaceTTL, got) - } - if got := svc.maxCap(); got != defaultMaxWorkspaces { - t.Errorf("expected fallback max cap %d, got %d", defaultMaxWorkspaces, got) - } -} diff --git a/internal/bugseti/config.go b/internal/bugseti/config.go deleted file mode 100644 index fe8776ed..00000000 --- a/internal/bugseti/config.go +++ /dev/null @@ -1,646 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "encoding/json" - "log" - "os" - "path/filepath" - "sync" - "time" -) - -// ConfigService manages application configuration and persistence. -type ConfigService struct { - config *Config - path string - mu sync.RWMutex -} - -// Config holds all BugSETI configuration. -type Config struct { - // Authentication — Forgejo API (resolved via pkg/forge config if empty) - ForgeURL string `json:"forgeUrl,omitempty"` - ForgeToken string `json:"forgeToken,omitempty"` - - // Hub coordination (agentic portal) - HubURL string `json:"hubUrl,omitempty"` - HubToken string `json:"hubToken,omitempty"` - ClientID string `json:"clientId,omitempty"` - ClientName string `json:"clientName,omitempty"` - - // Deprecated: use ForgeToken. Kept for migration. - GitHubToken string `json:"githubToken,omitempty"` - - // Repositories - WatchedRepos []string `json:"watchedRepos"` - Labels []string `json:"labels"` - - // Scheduling - WorkHours *WorkHours `json:"workHours,omitempty"` - FetchInterval int `json:"fetchIntervalMinutes"` - - // Notifications - NotificationsEnabled bool `json:"notificationsEnabled"` - NotificationSound bool `json:"notificationSound"` - - // Workspace - WorkspaceDir string `json:"workspaceDir,omitempty"` - DataDir string `json:"dataDir,omitempty"` - // Marketplace MCP - MarketplaceMCPRoot string `json:"marketplaceMcpRoot,omitempty"` - - // Onboarding - Onboarded bool `json:"onboarded"` - OnboardedAt time.Time `json:"onboardedAt,omitempty"` - - // UI Preferences - Theme string `json:"theme"` - ShowTrayPanel bool `json:"showTrayPanel"` - - // Advanced - MaxConcurrentIssues int `json:"maxConcurrentIssues"` - AutoSeedContext bool `json:"autoSeedContext"` - - // Workspace cache - MaxWorkspaces int `json:"maxWorkspaces"` // Upper bound on cached workspace entries (0 = default 100) - WorkspaceTTLMinutes int `json:"workspaceTtlMinutes"` // TTL for workspace entries in minutes (0 = default 1440 = 24h) - - // Updates - UpdateChannel string `json:"updateChannel"` // stable, beta, nightly - AutoUpdate bool `json:"autoUpdate"` // Automatically install updates - UpdateCheckInterval int `json:"updateCheckInterval"` // Check interval in hours (0 = disabled) - LastUpdateCheck time.Time `json:"lastUpdateCheck,omitempty"` -} - -// WorkHours defines when BugSETI should actively fetch issues. -type WorkHours struct { - Enabled bool `json:"enabled"` - StartHour int `json:"startHour"` // 0-23 - EndHour int `json:"endHour"` // 0-23 - Days []int `json:"days"` // 0=Sunday, 6=Saturday - Timezone string `json:"timezone"` -} - -// NewConfigService creates a new ConfigService with default values. -func NewConfigService() *ConfigService { - // Determine config path - configDir, err := os.UserConfigDir() - if err != nil { - configDir = filepath.Join(os.Getenv("HOME"), ".config") - } - - bugsetiDir := filepath.Join(configDir, "bugseti") - if err := os.MkdirAll(bugsetiDir, 0755); err != nil { - log.Printf("Warning: could not create config directory: %v", err) - } - - return &ConfigService{ - path: filepath.Join(bugsetiDir, "config.json"), - config: &Config{ - WatchedRepos: []string{}, - Labels: []string{ - "good first issue", - "help wanted", - "beginner-friendly", - }, - FetchInterval: 15, - NotificationsEnabled: true, - NotificationSound: true, - Theme: "dark", - ShowTrayPanel: true, - MaxConcurrentIssues: 1, - AutoSeedContext: true, - DataDir: bugsetiDir, - MarketplaceMCPRoot: "", - MaxWorkspaces: 100, - WorkspaceTTLMinutes: 1440, // 24 hours - UpdateChannel: "stable", - AutoUpdate: false, - UpdateCheckInterval: 6, // Check every 6 hours - }, - } -} - -// ServiceName returns the service name for Wails. -func (c *ConfigService) ServiceName() string { - return "ConfigService" -} - -// Load reads the configuration from disk. -func (c *ConfigService) Load() error { - c.mu.Lock() - defer c.mu.Unlock() - - data, err := os.ReadFile(c.path) - if err != nil { - if os.IsNotExist(err) { - // No config file yet, use defaults - return c.saveUnsafe() - } - return err - } - - var config Config - if err := json.Unmarshal(data, &config); err != nil { - return err - } - - // Merge with defaults for any new fields - c.mergeDefaults(&config) - c.config = &config - return nil -} - -// Save persists the configuration to disk. -func (c *ConfigService) Save() error { - c.mu.Lock() - defer c.mu.Unlock() - return c.saveUnsafe() -} - -// saveUnsafe writes config without acquiring lock. -func (c *ConfigService) saveUnsafe() error { - data, err := json.MarshalIndent(c.config, "", " ") - if err != nil { - return err - } - return os.WriteFile(c.path, data, 0600) -} - -// mergeDefaults fills in default values for any unset fields. -func (c *ConfigService) mergeDefaults(config *Config) { - if config.Labels == nil || len(config.Labels) == 0 { - config.Labels = c.config.Labels - } - if config.FetchInterval == 0 { - config.FetchInterval = 15 - } - if config.Theme == "" { - config.Theme = "dark" - } - if config.MaxConcurrentIssues == 0 { - config.MaxConcurrentIssues = 1 - } - if config.DataDir == "" { - config.DataDir = c.config.DataDir - } - if config.MaxWorkspaces == 0 { - config.MaxWorkspaces = 100 - } - if config.WorkspaceTTLMinutes == 0 { - config.WorkspaceTTLMinutes = 1440 - } - if config.UpdateChannel == "" { - config.UpdateChannel = "stable" - } - if config.UpdateCheckInterval == 0 { - config.UpdateCheckInterval = 6 - } -} - -// GetConfig returns a copy of the current configuration. -func (c *ConfigService) GetConfig() Config { - c.mu.RLock() - defer c.mu.RUnlock() - return *c.config -} - -// GetMarketplaceMCPRoot returns the configured marketplace MCP root path. -func (c *ConfigService) GetMarketplaceMCPRoot() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.MarketplaceMCPRoot -} - -// SetConfig updates the configuration and saves it. -func (c *ConfigService) SetConfig(config Config) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config = &config - return c.saveUnsafe() -} - -// GetWatchedRepos returns the list of watched repositories. -func (c *ConfigService) GetWatchedRepos() []string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.WatchedRepos -} - -// AddWatchedRepo adds a repository to the watch list. -func (c *ConfigService) AddWatchedRepo(repo string) error { - c.mu.Lock() - defer c.mu.Unlock() - - for _, r := range c.config.WatchedRepos { - if r == repo { - return nil // Already watching - } - } - - c.config.WatchedRepos = append(c.config.WatchedRepos, repo) - return c.saveUnsafe() -} - -// RemoveWatchedRepo removes a repository from the watch list. -func (c *ConfigService) RemoveWatchedRepo(repo string) error { - c.mu.Lock() - defer c.mu.Unlock() - - for i, r := range c.config.WatchedRepos { - if r == repo { - c.config.WatchedRepos = append(c.config.WatchedRepos[:i], c.config.WatchedRepos[i+1:]...) - return c.saveUnsafe() - } - } - - return nil -} - -// GetLabels returns the issue labels to filter by. -func (c *ConfigService) GetLabels() []string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.Labels -} - -// SetLabels updates the issue labels. -func (c *ConfigService) SetLabels(labels []string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.Labels = labels - return c.saveUnsafe() -} - -// GetFetchInterval returns the fetch interval as a duration. -func (c *ConfigService) GetFetchInterval() time.Duration { - c.mu.RLock() - defer c.mu.RUnlock() - return time.Duration(c.config.FetchInterval) * time.Minute -} - -// SetFetchInterval sets the fetch interval in minutes. -func (c *ConfigService) SetFetchInterval(minutes int) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.FetchInterval = minutes - return c.saveUnsafe() -} - -// IsWithinWorkHours checks if the current time is within configured work hours. -func (c *ConfigService) IsWithinWorkHours() bool { - c.mu.RLock() - defer c.mu.RUnlock() - - if c.config.WorkHours == nil || !c.config.WorkHours.Enabled { - return true // No work hours restriction - } - - wh := c.config.WorkHours - now := time.Now() - - // Check timezone - if wh.Timezone != "" { - loc, err := time.LoadLocation(wh.Timezone) - if err == nil { - now = now.In(loc) - } - } - - // Check day - day := int(now.Weekday()) - dayAllowed := false - for _, d := range wh.Days { - if d == day { - dayAllowed = true - break - } - } - if !dayAllowed { - return false - } - - // Check hour - hour := now.Hour() - if wh.StartHour <= wh.EndHour { - return hour >= wh.StartHour && hour < wh.EndHour - } - // Handle overnight (e.g., 22:00 - 06:00) - return hour >= wh.StartHour || hour < wh.EndHour -} - -// GetWorkHours returns the work hours configuration. -func (c *ConfigService) GetWorkHours() *WorkHours { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.WorkHours -} - -// SetWorkHours updates the work hours configuration. -func (c *ConfigService) SetWorkHours(wh *WorkHours) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.WorkHours = wh - return c.saveUnsafe() -} - -// IsNotificationsEnabled returns whether notifications are enabled. -func (c *ConfigService) IsNotificationsEnabled() bool { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.NotificationsEnabled -} - -// SetNotificationsEnabled enables or disables notifications. -func (c *ConfigService) SetNotificationsEnabled(enabled bool) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.NotificationsEnabled = enabled - return c.saveUnsafe() -} - -// GetWorkspaceDir returns the workspace directory. -func (c *ConfigService) GetWorkspaceDir() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.WorkspaceDir -} - -// SetWorkspaceDir sets the workspace directory. -func (c *ConfigService) SetWorkspaceDir(dir string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.WorkspaceDir = dir - return c.saveUnsafe() -} - -// GetDataDir returns the data directory. -func (c *ConfigService) GetDataDir() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.DataDir -} - -// IsOnboarded returns whether the user has completed onboarding. -func (c *ConfigService) IsOnboarded() bool { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.Onboarded -} - -// CompleteOnboarding marks onboarding as complete. -func (c *ConfigService) CompleteOnboarding() error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.Onboarded = true - c.config.OnboardedAt = time.Now() - return c.saveUnsafe() -} - -// GetTheme returns the current theme. -func (c *ConfigService) GetTheme() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.Theme -} - -// SetTheme sets the theme. -func (c *ConfigService) SetTheme(theme string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.Theme = theme - return c.saveUnsafe() -} - -// IsAutoSeedEnabled returns whether automatic context seeding is enabled. -func (c *ConfigService) IsAutoSeedEnabled() bool { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.AutoSeedContext -} - -// SetAutoSeedEnabled enables or disables automatic context seeding. -func (c *ConfigService) SetAutoSeedEnabled(enabled bool) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.AutoSeedContext = enabled - return c.saveUnsafe() -} - -// GetMaxWorkspaces returns the maximum number of cached workspaces. -func (c *ConfigService) GetMaxWorkspaces() int { - c.mu.RLock() - defer c.mu.RUnlock() - if c.config.MaxWorkspaces <= 0 { - return 100 - } - return c.config.MaxWorkspaces -} - -// GetWorkspaceTTL returns the workspace TTL as a time.Duration. -func (c *ConfigService) GetWorkspaceTTL() time.Duration { - c.mu.RLock() - defer c.mu.RUnlock() - if c.config.WorkspaceTTLMinutes <= 0 { - return 24 * time.Hour - } - return time.Duration(c.config.WorkspaceTTLMinutes) * time.Minute -} - -// UpdateSettings holds update-related configuration. -type UpdateSettings struct { - Channel string `json:"channel"` - AutoUpdate bool `json:"autoUpdate"` - CheckInterval int `json:"checkInterval"` // Hours - LastCheck time.Time `json:"lastCheck"` -} - -// GetUpdateSettings returns the update settings. -func (c *ConfigService) GetUpdateSettings() UpdateSettings { - c.mu.RLock() - defer c.mu.RUnlock() - return UpdateSettings{ - Channel: c.config.UpdateChannel, - AutoUpdate: c.config.AutoUpdate, - CheckInterval: c.config.UpdateCheckInterval, - LastCheck: c.config.LastUpdateCheck, - } -} - -// SetUpdateSettings updates the update settings. -func (c *ConfigService) SetUpdateSettings(settings UpdateSettings) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.UpdateChannel = settings.Channel - c.config.AutoUpdate = settings.AutoUpdate - c.config.UpdateCheckInterval = settings.CheckInterval - return c.saveUnsafe() -} - -// GetUpdateChannel returns the update channel. -func (c *ConfigService) GetUpdateChannel() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.UpdateChannel -} - -// SetUpdateChannel sets the update channel. -func (c *ConfigService) SetUpdateChannel(channel string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.UpdateChannel = channel - return c.saveUnsafe() -} - -// IsAutoUpdateEnabled returns whether automatic updates are enabled. -func (c *ConfigService) IsAutoUpdateEnabled() bool { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.AutoUpdate -} - -// SetAutoUpdateEnabled enables or disables automatic updates. -func (c *ConfigService) SetAutoUpdateEnabled(enabled bool) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.AutoUpdate = enabled - return c.saveUnsafe() -} - -// GetUpdateCheckInterval returns the update check interval in hours. -func (c *ConfigService) GetUpdateCheckInterval() int { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.UpdateCheckInterval -} - -// SetUpdateCheckInterval sets the update check interval in hours. -func (c *ConfigService) SetUpdateCheckInterval(hours int) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.UpdateCheckInterval = hours - return c.saveUnsafe() -} - -// GetLastUpdateCheck returns the last update check time. -func (c *ConfigService) GetLastUpdateCheck() time.Time { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.LastUpdateCheck -} - -// SetLastUpdateCheck sets the last update check time. -func (c *ConfigService) SetLastUpdateCheck(t time.Time) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.LastUpdateCheck = t - return c.saveUnsafe() -} - -// GetForgeURL returns the configured Forge URL (may be empty to use pkg/forge defaults). -func (c *ConfigService) GetForgeURL() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.ForgeURL -} - -// GetForgeToken returns the configured Forge token (may be empty to use pkg/forge defaults). -func (c *ConfigService) GetForgeToken() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.ForgeToken -} - -// SetForgeURL sets the Forge URL. -func (c *ConfigService) SetForgeURL(url string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.ForgeURL = url - return c.saveUnsafe() -} - -// SetForgeToken sets the Forge token. -func (c *ConfigService) SetForgeToken(token string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.ForgeToken = token - return c.saveUnsafe() -} - -// GetHubURL returns the configured Hub URL. -func (c *ConfigService) GetHubURL() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.HubURL -} - -// SetHubURL sets the Hub URL. -func (c *ConfigService) SetHubURL(url string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.HubURL = url - return c.saveUnsafe() -} - -// GetHubToken returns the configured Hub token. -func (c *ConfigService) GetHubToken() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.HubToken -} - -// SetHubToken sets the Hub token. -func (c *ConfigService) SetHubToken(token string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.HubToken = token - return c.saveUnsafe() -} - -// GetClientID returns the configured client ID. -func (c *ConfigService) GetClientID() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.ClientID -} - -// SetClientID sets the client ID. -func (c *ConfigService) SetClientID(id string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.ClientID = id - return c.saveUnsafe() -} - -// GetClientName returns the configured client name. -func (c *ConfigService) GetClientName() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config.ClientName -} - -// SetClientName sets the client name. -func (c *ConfigService) SetClientName(name string) error { - c.mu.Lock() - defer c.mu.Unlock() - c.config.ClientName = name - return c.saveUnsafe() -} - -// ShouldCheckForUpdates returns true if it's time to check for updates. -func (c *ConfigService) ShouldCheckForUpdates() bool { - c.mu.RLock() - defer c.mu.RUnlock() - - if c.config.UpdateCheckInterval <= 0 { - return false // Updates disabled - } - - if c.config.LastUpdateCheck.IsZero() { - return true // Never checked - } - - interval := time.Duration(c.config.UpdateCheckInterval) * time.Hour - return time.Since(c.config.LastUpdateCheck) >= interval -} diff --git a/internal/bugseti/config_test.go b/internal/bugseti/config_test.go deleted file mode 100644 index 19ed143a..00000000 --- a/internal/bugseti/config_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package bugseti - -import ( - "os" - "testing" -) - -func TestConfigPermissions(t *testing.T) { - // Get a temporary file path - f, err := os.CreateTemp("", "bugseti-config-*.json") - if err != nil { - t.Fatal(err) - } - name := f.Name() - f.Close() - os.Remove(name) // Ensure it doesn't exist - defer os.Remove(name) - - c := &ConfigService{ - path: name, - config: &Config{}, - } - - if err := c.Save(); err != nil { - t.Fatalf("Save failed: %v", err) - } - - info, err := os.Stat(name) - if err != nil { - t.Fatal(err) - } - - mode := info.Mode().Perm() - if mode != 0600 { - t.Errorf("expected file permissions 0600, got %04o", mode) - } -} diff --git a/internal/bugseti/ethics_guard.go b/internal/bugseti/ethics_guard.go deleted file mode 100644 index 555ea138..00000000 --- a/internal/bugseti/ethics_guard.go +++ /dev/null @@ -1,252 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "bytes" - "context" - "encoding/xml" - "strings" - "sync" - "time" -) - -const ( - maxEnvRunes = 512 - maxTitleRunes = 160 - maxNotificationRunes = 200 - maxSummaryRunes = 4000 - maxBodyRunes = 8000 - maxFileRunes = 260 -) - -type EthicsGuard struct { - Modal string - Axioms map[string]any - Loaded bool -} - -var ( - ethicsGuardMu sync.Mutex - ethicsGuard *EthicsGuard - ethicsGuardRoot string -) - -func getEthicsGuard(ctx context.Context) *EthicsGuard { - return getEthicsGuardWithRoot(ctx, "") -} - -func getEthicsGuardWithRoot(ctx context.Context, rootHint string) *EthicsGuard { - rootHint = strings.TrimSpace(rootHint) - - ethicsGuardMu.Lock() - defer ethicsGuardMu.Unlock() - - if ethicsGuard != nil && ethicsGuardRoot == rootHint { - return ethicsGuard - } - - guard := loadEthicsGuard(ctx, rootHint) - if guard == nil { - guard = &EthicsGuard{} - } - - ethicsGuard = guard - ethicsGuardRoot = rootHint - if ethicsGuard == nil { - return &EthicsGuard{} - } - return ethicsGuard -} - -func guardFromMarketplace(ctx context.Context, client marketplaceClient) *EthicsGuard { - if client == nil { - return &EthicsGuard{} - } - if ctx == nil { - ctx = context.Background() - } - - ctx, cancel := context.WithTimeout(ctx, 5*time.Second) - defer cancel() - ethics, err := client.EthicsCheck(ctx) - if err != nil || ethics == nil { - return &EthicsGuard{} - } - - return &EthicsGuard{ - Modal: ethics.Modal, - Axioms: ethics.Axioms, - Loaded: true, - } -} - -func loadEthicsGuard(ctx context.Context, rootHint string) *EthicsGuard { - if ctx == nil { - ctx = context.Background() - } - - ctx, cancel := context.WithTimeout(ctx, 2*time.Second) - defer cancel() - client, err := newMarketplaceClient(ctx, rootHint) - if err != nil { - return &EthicsGuard{} - } - defer client.Close() - - ethics, err := client.EthicsCheck(ctx) - if err != nil || ethics == nil { - return &EthicsGuard{} - } - - return &EthicsGuard{ - Modal: ethics.Modal, - Axioms: ethics.Axioms, - Loaded: true, - } -} - -func (g *EthicsGuard) SanitizeEnv(value string) string { - return stripShellMeta(sanitizeInline(value, maxEnvRunes)) -} - -// stripShellMeta removes shell metacharacters that could allow command -// injection when a value is interpolated inside a shell environment variable. -func stripShellMeta(s string) string { - var b strings.Builder - b.Grow(len(s)) - for _, r := range s { - switch r { - case '`', '$', ';', '|', '&', '(', ')', '{', '}', '<', '>', '!', '\\', '\'', '"', '\n', '\r': - continue - default: - b.WriteRune(r) - } - } - return strings.TrimSpace(b.String()) -} - -func (g *EthicsGuard) SanitizeTitle(value string) string { - return sanitizeInline(value, maxTitleRunes) -} - -func (g *EthicsGuard) SanitizeNotification(value string) string { - return sanitizeInline(value, maxNotificationRunes) -} - -func (g *EthicsGuard) SanitizeSummary(value string) string { - return sanitizeMultiline(value, maxSummaryRunes) -} - -func (g *EthicsGuard) SanitizeBody(value string) string { - return sanitizeMultiline(value, maxBodyRunes) -} - -func (g *EthicsGuard) SanitizeFiles(values []string) []string { - if len(values) == 0 { - return nil - } - - seen := make(map[string]bool) - clean := make([]string, 0, len(values)) - for _, value := range values { - trimmed := sanitizeInline(value, maxFileRunes) - if trimmed == "" { - continue - } - if strings.Contains(trimmed, "..") { - continue - } - if seen[trimmed] { - continue - } - seen[trimmed] = true - clean = append(clean, trimmed) - } - return clean -} - -func (g *EthicsGuard) SanitizeList(values []string, maxRunes int) []string { - if len(values) == 0 { - return nil - } - if maxRunes <= 0 { - maxRunes = maxTitleRunes - } - clean := make([]string, 0, len(values)) - for _, value := range values { - trimmed := sanitizeInline(value, maxRunes) - if trimmed == "" { - continue - } - clean = append(clean, trimmed) - } - return clean -} - -func sanitizeInline(input string, maxRunes int) string { - return sanitizeText(input, maxRunes, false) -} - -func sanitizeMultiline(input string, maxRunes int) string { - return sanitizeText(input, maxRunes, true) -} - -func sanitizeText(input string, maxRunes int, allowNewlines bool) string { - if input == "" { - return "" - } - if maxRunes <= 0 { - maxRunes = maxSummaryRunes - } - - var b strings.Builder - count := 0 - for _, r := range input { - if r == '\r' { - continue - } - if r == '\n' { - if allowNewlines { - b.WriteRune(r) - count++ - } else { - b.WriteRune(' ') - count++ - } - if count >= maxRunes { - break - } - continue - } - if r == '\t' { - b.WriteRune(' ') - count++ - if count >= maxRunes { - break - } - continue - } - if r < 0x20 || r == 0x7f { - continue - } - b.WriteRune(r) - count++ - if count >= maxRunes { - break - } - } - - return strings.TrimSpace(b.String()) -} - -func escapeAppleScript(value string) string { - value = strings.ReplaceAll(value, "\\", "\\\\") - value = strings.ReplaceAll(value, "\"", "\\\"") - return value -} - -func escapePowerShellXML(value string) string { - var buffer bytes.Buffer - _ = xml.EscapeText(&buffer, []byte(value)) - return buffer.String() -} diff --git a/internal/bugseti/ethics_guard_test.go b/internal/bugseti/ethics_guard_test.go deleted file mode 100644 index 4784160a..00000000 --- a/internal/bugseti/ethics_guard_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package bugseti - -import ( - "testing" -) - -func TestSanitizeInline_Good(t *testing.T) { - input := "Hello world" - output := sanitizeInline(input, 50) - if output != input { - t.Fatalf("expected %q, got %q", input, output) - } -} - -func TestSanitizeInline_Bad(t *testing.T) { - input := "Hello\nworld\t\x00" - expected := "Hello world" - output := sanitizeInline(input, 50) - if output != expected { - t.Fatalf("expected %q, got %q", expected, output) - } -} - -func TestSanitizeMultiline_Ugly(t *testing.T) { - input := "ab\ncd\tef\x00" - output := sanitizeMultiline(input, 5) - if output != "ab\ncd" { - t.Fatalf("expected %q, got %q", "ab\ncd", output) - } -} - -func TestSanitizeEnv_Good(t *testing.T) { - g := &EthicsGuard{} - input := "owner/repo-name" - output := g.SanitizeEnv(input) - if output != input { - t.Fatalf("expected %q, got %q", input, output) - } -} - -func TestSanitizeEnv_Bad(t *testing.T) { - g := &EthicsGuard{} - - tests := []struct { - name string - input string - expected string - }{ - {"backtick", "owner/repo`whoami`", "owner/repowhoami"}, - {"dollar", "owner/repo$(id)", "owner/repoid"}, - {"semicolon", "owner/repo;rm -rf /", "owner/reporm -rf /"}, - {"pipe", "owner/repo|cat /etc/passwd", "owner/repocat /etc/passwd"}, - {"ampersand", "owner/repo&&echo pwned", "owner/repoecho pwned"}, - {"mixed", "`$;|&(){}<>!\\'\"\n\r", ""}, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - output := g.SanitizeEnv(tc.input) - if output != tc.expected { - t.Fatalf("expected %q, got %q", tc.expected, output) - } - }) - } -} - -func TestStripShellMeta_Ugly(t *testing.T) { - // All metacharacters should be stripped, leaving empty string - input := "`$;|&(){}<>!\\'\"" - output := stripShellMeta(input) - if output != "" { - t.Fatalf("expected empty string, got %q", output) - } -} diff --git a/internal/bugseti/fetcher.go b/internal/bugseti/fetcher.go deleted file mode 100644 index 4565b3dc..00000000 --- a/internal/bugseti/fetcher.go +++ /dev/null @@ -1,276 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "fmt" - "log" - "strings" - "sync" - "time" - - "forge.lthn.ai/core/go/pkg/forge" -) - -// FetcherService fetches issues from configured OSS repositories. -type FetcherService struct { - config *ConfigService - notify *NotifyService - forge *forge.Client - running bool - mu sync.RWMutex - stopCh chan struct{} - issuesCh chan []*Issue -} - -// NewFetcherService creates a new FetcherService. -func NewFetcherService(config *ConfigService, notify *NotifyService, forgeClient *forge.Client) *FetcherService { - return &FetcherService{ - config: config, - notify: notify, - forge: forgeClient, - issuesCh: make(chan []*Issue, 10), - } -} - -// ServiceName returns the service name for Wails. -func (f *FetcherService) ServiceName() string { - return "FetcherService" -} - -// Start begins fetching issues from configured repositories. -func (f *FetcherService) Start() error { - f.mu.Lock() - defer f.mu.Unlock() - - if f.running { - return nil - } - - f.running = true - f.stopCh = make(chan struct{}) - - go f.fetchLoop() - log.Println("FetcherService started") - return nil -} - -// Pause stops fetching issues. -func (f *FetcherService) Pause() { - f.mu.Lock() - defer f.mu.Unlock() - - if !f.running { - return - } - - f.running = false - close(f.stopCh) - log.Println("FetcherService paused") -} - -// IsRunning returns whether the fetcher is actively running. -func (f *FetcherService) IsRunning() bool { - f.mu.RLock() - defer f.mu.RUnlock() - return f.running -} - -// Issues returns a channel that receives batches of fetched issues. -func (f *FetcherService) Issues() <-chan []*Issue { - return f.issuesCh -} - -// fetchLoop periodically fetches issues from all configured repositories. -func (f *FetcherService) fetchLoop() { - // Initial fetch - f.fetchAll() - - // Set up ticker for periodic fetching - interval := f.config.GetFetchInterval() - if interval < time.Minute { - interval = 15 * time.Minute - } - ticker := time.NewTicker(interval) - defer ticker.Stop() - - for { - select { - case <-f.stopCh: - return - case <-ticker.C: - // Check if within work hours - if f.config.IsWithinWorkHours() { - f.fetchAll() - } - } - } -} - -// fetchAll fetches issues from all configured repositories. -func (f *FetcherService) fetchAll() { - repos := f.config.GetWatchedRepos() - if len(repos) == 0 { - log.Println("No repositories configured") - return - } - - var allIssues []*Issue - for _, repo := range repos { - issues, err := f.fetchFromRepo(repo) - if err != nil { - log.Printf("Error fetching from %s: %v", repo, err) - continue - } - allIssues = append(allIssues, issues...) - } - - if len(allIssues) > 0 { - select { - case f.issuesCh <- allIssues: - f.notify.Notify("BugSETI", fmt.Sprintf("Found %d new issues", len(allIssues))) - default: - // Channel full, skip - } - } -} - -// fetchFromRepo fetches issues from a single repository using the Forgejo API. -func (f *FetcherService) fetchFromRepo(repo string) ([]*Issue, error) { - owner, repoName, err := splitRepo(repo) - if err != nil { - return nil, err - } - - labels := f.config.GetLabels() - if len(labels) == 0 { - labels = []string{"good first issue", "help wanted", "beginner-friendly"} - } - - forgeIssues, err := f.forge.ListIssues(owner, repoName, forge.ListIssuesOpts{ - State: "open", - Labels: labels, - Limit: 20, - }) - if err != nil { - return nil, fmt.Errorf("forge list issues failed: %w", err) - } - - issues := make([]*Issue, 0, len(forgeIssues)) - for _, fi := range forgeIssues { - labelNames := make([]string, len(fi.Labels)) - for i, l := range fi.Labels { - labelNames[i] = l.Name - } - - author := "" - if fi.Poster != nil { - author = fi.Poster.UserName - } - - issues = append(issues, &Issue{ - ID: fmt.Sprintf("%s#%d", repo, fi.Index), - Number: int(fi.Index), - Repo: repo, - Title: fi.Title, - Body: fi.Body, - URL: fi.HTMLURL, - Labels: labelNames, - Author: author, - CreatedAt: fi.Created, - Priority: calculatePriority(labelNames), - }) - } - - return issues, nil -} - -// FetchIssue fetches a single issue by repo and number. -func (f *FetcherService) FetchIssue(repo string, number int) (*Issue, error) { - owner, repoName, err := splitRepo(repo) - if err != nil { - return nil, err - } - - fi, err := f.forge.GetIssue(owner, repoName, int64(number)) - if err != nil { - return nil, fmt.Errorf("forge get issue failed: %w", err) - } - - labelNames := make([]string, len(fi.Labels)) - for i, l := range fi.Labels { - labelNames[i] = l.Name - } - - author := "" - if fi.Poster != nil { - author = fi.Poster.UserName - } - - // Fetch comments - forgeComments, err := f.forge.ListIssueComments(owner, repoName, int64(number)) - if err != nil { - log.Printf("Warning: could not fetch comments for %s#%d: %v", repo, number, err) - } - - comments := make([]Comment, 0, len(forgeComments)) - for _, c := range forgeComments { - commentAuthor := "" - if c.Poster != nil { - commentAuthor = c.Poster.UserName - } - comments = append(comments, Comment{ - Author: commentAuthor, - Body: c.Body, - }) - } - - return &Issue{ - ID: fmt.Sprintf("%s#%d", repo, fi.Index), - Number: int(fi.Index), - Repo: repo, - Title: fi.Title, - Body: fi.Body, - URL: fi.HTMLURL, - Labels: labelNames, - Author: author, - CreatedAt: fi.Created, - Priority: calculatePriority(labelNames), - Comments: comments, - }, nil -} - -// splitRepo splits "owner/repo" into owner and repo parts. -func splitRepo(repo string) (string, string, error) { - parts := strings.SplitN(repo, "/", 2) - if len(parts) != 2 { - return "", "", fmt.Errorf("invalid repo format %q, expected owner/repo", repo) - } - return parts[0], parts[1], nil -} - -// calculatePriority assigns a priority score based on labels. -func calculatePriority(labels []string) int { - priority := 50 // Default priority - - for _, label := range labels { - lower := strings.ToLower(label) - switch { - case strings.Contains(lower, "good first issue"): - priority += 30 - case strings.Contains(lower, "help wanted"): - priority += 20 - case strings.Contains(lower, "beginner"): - priority += 25 - case strings.Contains(lower, "easy"): - priority += 20 - case strings.Contains(lower, "bug"): - priority += 10 - case strings.Contains(lower, "documentation"): - priority += 5 - case strings.Contains(lower, "priority"): - priority += 15 - } - } - - return priority -} diff --git a/internal/bugseti/fetcher_test.go b/internal/bugseti/fetcher_test.go deleted file mode 100644 index 2fdc1982..00000000 --- a/internal/bugseti/fetcher_test.go +++ /dev/null @@ -1,407 +0,0 @@ -package bugseti - -import ( - "encoding/json" - "fmt" - "os" - "os/exec" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -// testConfigService creates a ConfigService with in-memory config for testing. -func testConfigService(t *testing.T, repos []string, labels []string) *ConfigService { - t.Helper() - dir := t.TempDir() - cs := &ConfigService{ - path: dir + "/config.json", - config: &Config{ - WatchedRepos: repos, - Labels: labels, - FetchInterval: 15, - DataDir: dir, - }, - } - return cs -} - -// TestHelperProcess is invoked by the test binary when GO_TEST_HELPER_PROCESS -// is set. It prints the value of GO_TEST_HELPER_OUTPUT and optionally exits -// with a non-zero code. Kept for future exec.Command mocking. -func TestHelperProcess(t *testing.T) { - if os.Getenv("GO_TEST_HELPER_PROCESS") != "1" { - return - } - fmt.Fprint(os.Stdout, os.Getenv("GO_TEST_HELPER_OUTPUT")) - if os.Getenv("GO_TEST_HELPER_EXIT_ERROR") == "1" { - os.Exit(1) - } - os.Exit(0) -} - -// ---- NewFetcherService ---- - -func TestNewFetcherService_Good(t *testing.T) { - cfg := testConfigService(t, nil, nil) - notify := NewNotifyService(cfg) - f := NewFetcherService(cfg, notify, nil) - - require.NotNil(t, f) - assert.Equal(t, "FetcherService", f.ServiceName()) - assert.False(t, f.IsRunning()) - assert.NotNil(t, f.Issues()) -} - -// ---- Start / Pause / IsRunning lifecycle ---- - -func TestStartPause_Good(t *testing.T) { - cfg := testConfigService(t, nil, nil) - notify := NewNotifyService(cfg) - f := NewFetcherService(cfg, notify, nil) - - require.NoError(t, f.Start()) - assert.True(t, f.IsRunning()) - - // Starting again is a no-op. - require.NoError(t, f.Start()) - assert.True(t, f.IsRunning()) - - f.Pause() - assert.False(t, f.IsRunning()) - - // Pausing again is a no-op. - f.Pause() - assert.False(t, f.IsRunning()) -} - -// ---- calculatePriority ---- - -func TestCalculatePriority_Good(t *testing.T) { - tests := []struct { - name string - labels []string - expected int - }{ - {"no labels", nil, 50}, - {"good first issue", []string{"good first issue"}, 80}, - {"help wanted", []string{"Help Wanted"}, 70}, - {"beginner", []string{"beginner-friendly"}, 75}, - {"easy", []string{"Easy"}, 70}, - {"bug", []string{"bug"}, 60}, - {"documentation", []string{"Documentation"}, 55}, - {"priority", []string{"high-priority"}, 65}, - {"combined", []string{"good first issue", "bug"}, 90}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - assert.Equal(t, tt.expected, calculatePriority(tt.labels)) - }) - } -} - -func TestCalculatePriority_Bad(t *testing.T) { - // Unknown labels should not change priority from default. - assert.Equal(t, 50, calculatePriority([]string{"unknown-label", "something-else"})) -} - -// ---- Label query construction ---- - -func TestLabelQuery_Good(t *testing.T) { - // When config has custom labels, fetchFromRepo should use them. - cfg := testConfigService(t, []string{"owner/repo"}, []string{"custom-label", "another"}) - labels := cfg.GetLabels() - labelQuery := strings.Join(labels, ",") - assert.Equal(t, "custom-label,another", labelQuery) -} - -func TestLabelQuery_Bad(t *testing.T) { - // When config has empty labels, fetchFromRepo falls back to defaults. - cfg := testConfigService(t, []string{"owner/repo"}, nil) - labels := cfg.GetLabels() - if len(labels) == 0 { - labels = []string{"good first issue", "help wanted", "beginner-friendly"} - } - labelQuery := strings.Join(labels, ",") - assert.Equal(t, "good first issue,help wanted,beginner-friendly", labelQuery) -} - -// ---- fetchFromRepo with mocked gh CLI output ---- - -func TestFetchFromRepo_Good(t *testing.T) { - ghIssues := []struct { - Number int `json:"number"` - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` - CreatedAt time.Time `json:"createdAt"` - Author struct { - Login string `json:"login"` - } `json:"author"` - Labels []struct { - Name string `json:"name"` - } `json:"labels"` - }{ - { - Number: 42, - Title: "Fix login bug", - Body: "The login page crashes", - URL: "https://github.com/test/repo/issues/42", - CreatedAt: time.Date(2026, 1, 15, 10, 0, 0, 0, time.UTC), - }, - } - ghIssues[0].Author.Login = "octocat" - ghIssues[0].Labels = []struct { - Name string `json:"name"` - }{ - {Name: "good first issue"}, - {Name: "bug"}, - } - - output, err := json.Marshal(ghIssues) - require.NoError(t, err) - - // We can't easily intercept exec.CommandContext in the production code - // without refactoring, so we test the JSON parsing path by directly - // calling json.Unmarshal the same way fetchFromRepo does. - var parsed []struct { - Number int `json:"number"` - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` - CreatedAt time.Time `json:"createdAt"` - Author struct { - Login string `json:"login"` - } `json:"author"` - Labels []struct { - Name string `json:"name"` - } `json:"labels"` - } - require.NoError(t, json.Unmarshal(output, &parsed)) - require.Len(t, parsed, 1) - - gi := parsed[0] - labels := make([]string, len(gi.Labels)) - for i, l := range gi.Labels { - labels[i] = l.Name - } - - issue := &Issue{ - ID: fmt.Sprintf("%s#%d", "test/repo", gi.Number), - Number: gi.Number, - Repo: "test/repo", - Title: gi.Title, - Body: gi.Body, - URL: gi.URL, - Labels: labels, - Author: gi.Author.Login, - CreatedAt: gi.CreatedAt, - Priority: calculatePriority(labels), - } - - assert.Equal(t, "test/repo#42", issue.ID) - assert.Equal(t, 42, issue.Number) - assert.Equal(t, "Fix login bug", issue.Title) - assert.Equal(t, "octocat", issue.Author) - assert.Equal(t, []string{"good first issue", "bug"}, issue.Labels) - assert.Equal(t, 90, issue.Priority) // 50 + 30 (good first issue) + 10 (bug) -} - -func TestFetchFromRepo_Bad_InvalidJSON(t *testing.T) { - // Simulate gh returning invalid JSON. - var ghIssues []struct { - Number int `json:"number"` - } - err := json.Unmarshal([]byte(`not json at all`), &ghIssues) - assert.Error(t, err, "invalid JSON should produce an error") -} - -func TestFetchFromRepo_Bad_GhNotInstalled(t *testing.T) { - // Verify that a missing executable produces an exec error. - cmd := exec.Command("gh-nonexistent-binary-12345") - _, err := cmd.Output() - assert.Error(t, err, "missing binary should produce an error") -} - -// ---- fetchAll: no repos configured ---- - -func TestFetchAll_Bad_NoRepos(t *testing.T) { - cfg := testConfigService(t, nil, nil) - notify := NewNotifyService(cfg) - f := NewFetcherService(cfg, notify, nil) - - // fetchAll with no repos should not panic and should not send to channel. - f.fetchAll() - - // Channel should be empty. - select { - case <-f.issuesCh: - t.Fatal("expected no issues on channel when no repos configured") - default: - // expected - } -} - -// ---- Channel backpressure ---- - -func TestChannelBackpressure_Ugly(t *testing.T) { - cfg := testConfigService(t, nil, nil) - notify := NewNotifyService(cfg) - f := NewFetcherService(cfg, notify, nil) - - // Fill the channel to capacity (buffer size is 10). - for i := 0; i < 10; i++ { - f.issuesCh <- []*Issue{{ID: fmt.Sprintf("test#%d", i)}} - } - - // Now try to send via the select path (same logic as fetchAll). - // This should be a non-blocking drop, not a deadlock. - done := make(chan struct{}) - go func() { - defer close(done) - issues := []*Issue{{ID: "overflow#1"}} - select { - case f.issuesCh <- issues: - // Shouldn't happen — channel is full. - t.Error("expected channel send to be skipped due to backpressure") - default: - // This is the expected path — channel full, message dropped. - } - }() - - select { - case <-done: - // success — did not deadlock - case <-time.After(time.Second): - t.Fatal("backpressure test timed out — possible deadlock") - } -} - -// ---- FetchIssue single-issue parsing ---- - -func TestFetchIssue_Good_Parse(t *testing.T) { - // Test the JSON parsing and Issue construction for FetchIssue. - ghIssue := struct { - Number int `json:"number"` - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` - CreatedAt time.Time `json:"createdAt"` - Author struct { - Login string `json:"login"` - } `json:"author"` - Labels []struct { - Name string `json:"name"` - } `json:"labels"` - Comments []struct { - Body string `json:"body"` - Author struct { - Login string `json:"login"` - } `json:"author"` - } `json:"comments"` - }{ - Number: 99, - Title: "Add dark mode", - Body: "Please add dark mode support", - URL: "https://github.com/test/repo/issues/99", - CreatedAt: time.Date(2026, 2, 1, 12, 0, 0, 0, time.UTC), - } - ghIssue.Author.Login = "contributor" - ghIssue.Labels = []struct { - Name string `json:"name"` - }{ - {Name: "help wanted"}, - } - ghIssue.Comments = []struct { - Body string `json:"body"` - Author struct { - Login string `json:"login"` - } `json:"author"` - }{ - {Body: "I can work on this"}, - } - ghIssue.Comments[0].Author.Login = "volunteer" - - data, err := json.Marshal(ghIssue) - require.NoError(t, err) - - // Re-parse as the function would. - var parsed struct { - Number int `json:"number"` - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` - CreatedAt time.Time `json:"createdAt"` - Author struct { - Login string `json:"login"` - } `json:"author"` - Labels []struct { - Name string `json:"name"` - } `json:"labels"` - Comments []struct { - Body string `json:"body"` - Author struct { - Login string `json:"login"` - } `json:"author"` - } `json:"comments"` - } - require.NoError(t, json.Unmarshal(data, &parsed)) - - labels := make([]string, len(parsed.Labels)) - for i, l := range parsed.Labels { - labels[i] = l.Name - } - comments := make([]Comment, len(parsed.Comments)) - for i, c := range parsed.Comments { - comments[i] = Comment{Author: c.Author.Login, Body: c.Body} - } - - issue := &Issue{ - ID: fmt.Sprintf("%s#%d", "test/repo", parsed.Number), - Number: parsed.Number, - Repo: "test/repo", - Title: parsed.Title, - Body: parsed.Body, - URL: parsed.URL, - Labels: labels, - Author: parsed.Author.Login, - CreatedAt: parsed.CreatedAt, - Priority: calculatePriority(labels), - Comments: comments, - } - - assert.Equal(t, "test/repo#99", issue.ID) - assert.Equal(t, "contributor", issue.Author) - assert.Equal(t, 70, issue.Priority) // 50 + 20 (help wanted) - require.Len(t, issue.Comments, 1) - assert.Equal(t, "volunteer", issue.Comments[0].Author) - assert.Equal(t, "I can work on this", issue.Comments[0].Body) -} - -// ---- Issues() channel accessor ---- - -func TestIssuesChannel_Good(t *testing.T) { - cfg := testConfigService(t, nil, nil) - notify := NewNotifyService(cfg) - f := NewFetcherService(cfg, notify, nil) - - ch := f.Issues() - require.NotNil(t, ch) - - // Send and receive through the channel. - go func() { - f.issuesCh <- []*Issue{{ID: "test#1", Title: "Test issue"}} - }() - - select { - case issues := <-ch: - require.Len(t, issues, 1) - assert.Equal(t, "test#1", issues[0].ID) - case <-time.After(time.Second): - t.Fatal("timed out waiting for issues on channel") - } -} diff --git a/internal/bugseti/ghcheck.go b/internal/bugseti/ghcheck.go deleted file mode 100644 index bf33f3e9..00000000 --- a/internal/bugseti/ghcheck.go +++ /dev/null @@ -1,22 +0,0 @@ -package bugseti - -import ( - "forge.lthn.ai/core/go/pkg/forge" -) - -// CheckForge verifies that the Forgejo API is configured and reachable. -// Returns nil if a token is configured and the API responds, or an error -// with actionable instructions for the user. -func CheckForge() (*forge.Client, error) { - client, err := forge.NewFromConfig("", "") - if err != nil { - return nil, err - } - - // Verify the token works by fetching the current user - if _, err := client.GetCurrentUser(); err != nil { - return nil, err - } - - return client, nil -} diff --git a/internal/bugseti/ghcheck_test.go b/internal/bugseti/ghcheck_test.go deleted file mode 100644 index b2fc10dc..00000000 --- a/internal/bugseti/ghcheck_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package bugseti - -import ( - "os" - "testing" -) - -func TestCheckForge_Bad_MissingConfig(t *testing.T) { - // Clear any env-based forge config to ensure CheckForge fails - t.Setenv("FORGE_TOKEN", "") - t.Setenv("FORGE_URL", "") - - // Point HOME to a temp dir so no config file is found - t.Setenv("HOME", t.TempDir()) - if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) - } - - _, err := CheckForge() - if err == nil { - t.Fatal("expected error when forge is not configured") - } -} diff --git a/internal/bugseti/go.mod b/internal/bugseti/go.mod deleted file mode 100644 index 62eaa655..00000000 --- a/internal/bugseti/go.mod +++ /dev/null @@ -1,32 +0,0 @@ -module forge.lthn.ai/core/cli/internal/bugseti - -go 1.25.5 - -require ( - codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 - github.com/mark3labs/mcp-go v0.43.2 - github.com/stretchr/testify v1.11.1 -) - -require ( - github.com/42wim/httpsig v1.2.3 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect - github.com/buger/jsonparser v1.1.1 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/davidmz/go-pageant v1.0.2 // indirect - github.com/go-fed/httpsig v1.1.0 // indirect - github.com/google/go-cmp v0.7.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect - github.com/invopop/jsonschema v0.13.0 // indirect - github.com/mailru/easyjson v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/rogpeppe/go-internal v1.14.1 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/sys v0.40.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/internal/bugseti/go.sum b/internal/bugseti/go.sum deleted file mode 100644 index 1c248236..00000000 --- a/internal/bugseti/go.sum +++ /dev/null @@ -1,39 +0,0 @@ -codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 h1:HTCWpzyWQOHDWt3LzI6/d2jvUDsw/vgGRWm/8BTvcqI= -github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= -github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8= -github.com/mark3labs/mcp-go v0.43.2 h1:21PUSlWWiSbUPQwXIJ5WKlETixpFpq+WBpbMGDSVy/I= -github.com/mark3labs/mcp-go v0.43.2/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= -github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= -github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/bugseti/hub.go b/internal/bugseti/hub.go deleted file mode 100644 index 664c1189..00000000 --- a/internal/bugseti/hub.go +++ /dev/null @@ -1,576 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "bytes" - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "log" - "net/http" - "net/url" - "os" - "path/filepath" - "runtime" - "sync" - "time" - - "forge.lthn.ai/core/go/pkg/forge" -) - -// HubService coordinates with the agentic portal for issue assignment and leaderboard. -type HubService struct { - config *ConfigService - client *http.Client - connected bool - pending []PendingOp - mu sync.RWMutex -} - -// PendingOp represents an operation queued for retry when the hub is unreachable. -type PendingOp struct { - Method string `json:"method"` - Path string `json:"path"` - Body json.RawMessage `json:"body,omitempty"` - CreatedAt time.Time `json:"createdAt"` -} - -// HubClaim represents a claimed issue from the hub. -type HubClaim struct { - ID string `json:"id"` - IssueURL string `json:"issueUrl"` - ClientID string `json:"clientId"` - ClaimedAt time.Time `json:"claimedAt"` - ExpiresAt time.Time `json:"expiresAt"` - Status string `json:"status"` -} - -// LeaderboardEntry represents a single entry on the leaderboard. -type LeaderboardEntry struct { - ClientID string `json:"clientId"` - ClientName string `json:"clientName"` - Score int `json:"score"` - PRsMerged int `json:"prsMerged"` - Rank int `json:"rank"` -} - -// GlobalStats holds aggregate statistics from the hub. -type GlobalStats struct { - TotalClients int `json:"totalClients"` - TotalClaims int `json:"totalClaims"` - TotalPRsMerged int `json:"totalPrsMerged"` - ActiveClaims int `json:"activeClaims"` - IssuesAvailable int `json:"issuesAvailable"` -} - -// ConflictError indicates a 409 response from the hub (e.g. issue already claimed). -type ConflictError struct { - StatusCode int -} - -func (e *ConflictError) Error() string { - return fmt.Sprintf("conflict: status %d", e.StatusCode) -} - -// NotFoundError indicates a 404 response from the hub. -type NotFoundError struct { - StatusCode int -} - -func (e *NotFoundError) Error() string { - return fmt.Sprintf("not found: status %d", e.StatusCode) -} - -// NewHubService creates a new HubService with the given config. -// If the config has no ClientID, one is generated and persisted. -func NewHubService(config *ConfigService) *HubService { - h := &HubService{ - config: config, - client: &http.Client{ - Timeout: 10 * time.Second, - }, - pending: make([]PendingOp, 0), - } - - // Generate client ID if not set. - if config.GetClientID() == "" { - id := generateClientID() - _ = config.SetClientID(id) - } - - h.loadPendingOps() - - return h -} - -// ServiceName returns the service name for Wails. -func (h *HubService) ServiceName() string { - return "HubService" -} - -// GetClientID returns the client ID from config. -func (h *HubService) GetClientID() string { - return h.config.GetClientID() -} - -// IsConnected returns whether the hub was reachable on the last request. -func (h *HubService) IsConnected() bool { - h.mu.RLock() - defer h.mu.RUnlock() - return h.connected -} - -// generateClientID creates a random hex string (16 bytes = 32 hex chars). -func generateClientID() string { - b := make([]byte, 16) - if _, err := rand.Read(b); err != nil { - // Fallback: this should never happen with crypto/rand. - return fmt.Sprintf("fallback-%d", time.Now().UnixNano()) - } - return hex.EncodeToString(b) -} - -// doRequest builds and executes an HTTP request against the hub API. -// It returns the raw *http.Response and any transport-level error. -func (h *HubService) doRequest(method, path string, body interface{}) (*http.Response, error) { - hubURL := h.config.GetHubURL() - if hubURL == "" { - return nil, fmt.Errorf("hub URL not configured") - } - - fullURL := hubURL + "/api/bugseti" + path - - var bodyReader io.Reader - if body != nil { - data, err := json.Marshal(body) - if err != nil { - return nil, fmt.Errorf("marshal request body: %w", err) - } - bodyReader = bytes.NewReader(data) - } - - req, err := http.NewRequest(method, fullURL, bodyReader) - if err != nil { - return nil, fmt.Errorf("build request: %w", err) - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json") - - token := h.config.GetHubToken() - if token != "" { - req.Header.Set("Authorization", "Bearer "+token) - } - - resp, err := h.client.Do(req) - if err != nil { - h.mu.Lock() - h.connected = false - h.mu.Unlock() - return nil, err - } - - h.mu.Lock() - h.connected = true - h.mu.Unlock() - - return resp, nil -} - -// doJSON executes an HTTP request and decodes the JSON response into dest. -// It handles common error status codes with typed errors. -func (h *HubService) doJSON(method, path string, body, dest interface{}) error { - resp, err := h.doRequest(method, path, body) - if err != nil { - return err - } - defer resp.Body.Close() - - switch { - case resp.StatusCode == http.StatusUnauthorized: - return fmt.Errorf("unauthorised") - case resp.StatusCode == http.StatusConflict: - return &ConflictError{StatusCode: resp.StatusCode} - case resp.StatusCode == http.StatusNotFound: - return &NotFoundError{StatusCode: resp.StatusCode} - case resp.StatusCode >= 400: - respBody, _ := io.ReadAll(resp.Body) - return fmt.Errorf("hub error %d: %s", resp.StatusCode, string(respBody)) - } - - if dest != nil { - if err := json.NewDecoder(resp.Body).Decode(dest); err != nil { - return fmt.Errorf("decode response: %w", err) - } - } - - return nil -} - -// queueOp marshals body to JSON and appends a PendingOp to the queue. -func (h *HubService) queueOp(method, path string, body interface{}) { - var raw json.RawMessage - if body != nil { - data, err := json.Marshal(body) - if err != nil { - log.Printf("BugSETI: queueOp marshal error: %v", err) - return - } - raw = data - } - - h.mu.Lock() - h.pending = append(h.pending, PendingOp{ - Method: method, - Path: path, - Body: raw, - CreatedAt: time.Now(), - }) - h.mu.Unlock() - - h.savePendingOps() -} - -// drainPendingOps replays queued operations against the hub. -// 5xx/transport errors are kept for retry; 4xx responses are dropped (stale). -func (h *HubService) drainPendingOps() { - h.mu.Lock() - ops := h.pending - h.pending = make([]PendingOp, 0) - h.mu.Unlock() - - if len(ops) == 0 { - return - } - - var failed []PendingOp - for _, op := range ops { - var body interface{} - if len(op.Body) > 0 { - body = json.RawMessage(op.Body) - } - - resp, err := h.doRequest(op.Method, op.Path, body) - if err != nil { - // Transport error — keep for retry. - failed = append(failed, op) - continue - } - resp.Body.Close() - - if resp.StatusCode >= 500 { - // Server error — keep for retry. - failed = append(failed, op) - } // 4xx are dropped (stale). - } - - if len(failed) > 0 { - h.mu.Lock() - h.pending = append(failed, h.pending...) - h.mu.Unlock() - } - - h.savePendingOps() -} - -// savePendingOps persists the pending operations queue to disk. -func (h *HubService) savePendingOps() { - dataDir := h.config.GetDataDir() - if dataDir == "" { - return - } - - h.mu.RLock() - data, err := json.Marshal(h.pending) - h.mu.RUnlock() - if err != nil { - log.Printf("BugSETI: savePendingOps marshal error: %v", err) - return - } - - path := filepath.Join(dataDir, "hub_pending.json") - if err := os.WriteFile(path, data, 0600); err != nil { - log.Printf("BugSETI: savePendingOps write error: %v", err) - } -} - -// loadPendingOps loads the pending operations queue from disk. -// Errors are silently ignored (the file may not exist yet). -func (h *HubService) loadPendingOps() { - dataDir := h.config.GetDataDir() - if dataDir == "" { - return - } - - path := filepath.Join(dataDir, "hub_pending.json") - data, err := os.ReadFile(path) - if err != nil { - return - } - - var ops []PendingOp - if err := json.Unmarshal(data, &ops); err != nil { - return - } - h.pending = ops -} - -// PendingCount returns the number of queued pending operations. -func (h *HubService) PendingCount() int { - h.mu.RLock() - defer h.mu.RUnlock() - return len(h.pending) -} - -// ---- Task 4: Auto-Register via Forge Token ---- - -// AutoRegister exchanges a Forge API token for a hub API key. -// If a hub token is already configured, this is a no-op. -func (h *HubService) AutoRegister() error { - // Skip if already registered. - if h.config.GetHubToken() != "" { - return nil - } - - hubURL := h.config.GetHubURL() - if hubURL == "" { - return fmt.Errorf("hub URL not configured") - } - - // Resolve forge credentials from config/env. - forgeURL := h.config.GetForgeURL() - forgeToken := h.config.GetForgeToken() - if forgeToken == "" { - resolvedURL, resolvedToken, err := forge.ResolveConfig(forgeURL, "") - if err != nil { - return fmt.Errorf("resolve forge config: %w", err) - } - forgeURL = resolvedURL - forgeToken = resolvedToken - } - - if forgeToken == "" { - return fmt.Errorf("no forge token available (set FORGE_TOKEN or run: core forge config --token TOKEN)") - } - - // Build request body. - payload := map[string]string{ - "forge_url": forgeURL, - "forge_token": forgeToken, - "client_id": h.config.GetClientID(), - } - data, err := json.Marshal(payload) - if err != nil { - return fmt.Errorf("marshal auto-register body: %w", err) - } - - // POST directly (no bearer token yet). - resp, err := h.client.Post(hubURL+"/api/bugseti/auth/forge", "application/json", bytes.NewReader(data)) - if err != nil { - h.mu.Lock() - h.connected = false - h.mu.Unlock() - return fmt.Errorf("auto-register request: %w", err) - } - defer resp.Body.Close() - - h.mu.Lock() - h.connected = true - h.mu.Unlock() - - if resp.StatusCode >= 400 { - respBody, _ := io.ReadAll(resp.Body) - return fmt.Errorf("auto-register failed %d: %s", resp.StatusCode, string(respBody)) - } - - var result struct { - APIKey string `json:"api_key"` - } - if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { - return fmt.Errorf("decode auto-register response: %w", err) - } - - if err := h.config.SetHubToken(result.APIKey); err != nil { - return fmt.Errorf("cache hub token: %w", err) - } - - log.Printf("BugSETI: auto-registered with hub, token cached") - return nil -} - -// ---- Task 5: Write Operations ---- - -// Register registers this client with the hub. -func (h *HubService) Register() error { - h.drainPendingOps() - - name := h.config.GetClientName() - clientID := h.config.GetClientID() - if name == "" { - if len(clientID) >= 8 { - name = "BugSETI-" + clientID[:8] - } else { - name = "BugSETI-" + clientID - } - } - - body := map[string]string{ - "client_id": clientID, - "name": name, - "version": GetVersion(), - "os": runtime.GOOS, - "arch": runtime.GOARCH, - } - - return h.doJSON("POST", "/register", body, nil) -} - -// Heartbeat sends a heartbeat to the hub. -func (h *HubService) Heartbeat() error { - body := map[string]string{ - "client_id": h.config.GetClientID(), - } - return h.doJSON("POST", "/heartbeat", body, nil) -} - -// ClaimIssue claims an issue on the hub, returning the claim details. -// Returns a ConflictError if the issue is already claimed by another client. -func (h *HubService) ClaimIssue(issue *Issue) (*HubClaim, error) { - h.drainPendingOps() - - body := map[string]interface{}{ - "client_id": h.config.GetClientID(), - "issue_id": issue.ID, - "repo": issue.Repo, - "issue_number": issue.Number, - "title": issue.Title, - "url": issue.URL, - } - - var claim HubClaim - if err := h.doJSON("POST", "/issues/claim", body, &claim); err != nil { - return nil, err - } - return &claim, nil -} - -// UpdateStatus updates the status of a claimed issue on the hub. -func (h *HubService) UpdateStatus(issueID, status, prURL string, prNumber int) error { - body := map[string]interface{}{ - "client_id": h.config.GetClientID(), - "status": status, - } - if prURL != "" { - body["pr_url"] = prURL - } - if prNumber > 0 { - body["pr_number"] = prNumber - } - - path := "/issues/" + url.PathEscape(issueID) + "/status" - return h.doJSON("PATCH", path, body, nil) -} - -// ReleaseClaim releases a previously claimed issue back to the pool. -func (h *HubService) ReleaseClaim(issueID string) error { - body := map[string]string{ - "client_id": h.config.GetClientID(), - } - - path := "/issues/" + url.PathEscape(issueID) + "/claim" - return h.doJSON("DELETE", path, body, nil) -} - -// SyncStats uploads local statistics to the hub. -func (h *HubService) SyncStats(stats *Stats) error { - // Build repos_contributed as a flat string slice from the map keys. - repos := make([]string, 0, len(stats.ReposContributed)) - for k := range stats.ReposContributed { - repos = append(repos, k) - } - - body := map[string]interface{}{ - "client_id": h.config.GetClientID(), - "stats": map[string]interface{}{ - "issues_attempted": stats.IssuesAttempted, - "issues_completed": stats.IssuesCompleted, - "issues_skipped": stats.IssuesSkipped, - "prs_submitted": stats.PRsSubmitted, - "prs_merged": stats.PRsMerged, - "prs_rejected": stats.PRsRejected, - "current_streak": stats.CurrentStreak, - "longest_streak": stats.LongestStreak, - "total_time_minutes": int(stats.TotalTimeSpent.Minutes()), - "repos_contributed": repos, - }, - } - - return h.doJSON("POST", "/stats/sync", body, nil) -} - -// ---- Task 6: Read Operations ---- - -// IsIssueClaimed checks whether an issue is currently claimed on the hub. -// Returns the claim if it exists, or (nil, nil) if the issue is not claimed (404). -func (h *HubService) IsIssueClaimed(issueID string) (*HubClaim, error) { - path := "/issues/" + url.PathEscape(issueID) - - var claim HubClaim - if err := h.doJSON("GET", path, nil, &claim); err != nil { - if _, ok := err.(*NotFoundError); ok { - return nil, nil - } - return nil, err - } - return &claim, nil -} - -// ListClaims returns claimed issues, optionally filtered by status and/or repo. -func (h *HubService) ListClaims(status, repo string) ([]*HubClaim, error) { - params := url.Values{} - if status != "" { - params.Set("status", status) - } - if repo != "" { - params.Set("repo", repo) - } - - path := "/issues/claimed" - if encoded := params.Encode(); encoded != "" { - path += "?" + encoded - } - - var claims []*HubClaim - if err := h.doJSON("GET", path, nil, &claims); err != nil { - return nil, err - } - return claims, nil -} - -// leaderboardResponse wraps the hub leaderboard JSON envelope. -type leaderboardResponse struct { - Entries []LeaderboardEntry `json:"entries"` - TotalParticipants int `json:"totalParticipants"` -} - -// GetLeaderboard fetches the top N leaderboard entries from the hub. -func (h *HubService) GetLeaderboard(limit int) ([]LeaderboardEntry, int, error) { - path := fmt.Sprintf("/leaderboard?limit=%d", limit) - - var resp leaderboardResponse - if err := h.doJSON("GET", path, nil, &resp); err != nil { - return nil, 0, err - } - return resp.Entries, resp.TotalParticipants, nil -} - -// GetGlobalStats fetches aggregate statistics from the hub. -func (h *HubService) GetGlobalStats() (*GlobalStats, error) { - var stats GlobalStats - if err := h.doJSON("GET", "/stats", nil, &stats); err != nil { - return nil, err - } - return &stats, nil -} diff --git a/internal/bugseti/hub_test.go b/internal/bugseti/hub_test.go deleted file mode 100644 index e5236daf..00000000 --- a/internal/bugseti/hub_test.go +++ /dev/null @@ -1,558 +0,0 @@ -package bugseti - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "os" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func testHubService(t *testing.T, serverURL string) *HubService { - t.Helper() - cfg := testConfigService(t, nil, nil) - if serverURL != "" { - cfg.config.HubURL = serverURL - } - return NewHubService(cfg) -} - -// ---- NewHubService ---- - -func TestNewHubService_Good(t *testing.T) { - h := testHubService(t, "") - require.NotNil(t, h) - assert.NotNil(t, h.config) - assert.NotNil(t, h.client) - assert.False(t, h.IsConnected()) -} - -func TestHubServiceName_Good(t *testing.T) { - h := testHubService(t, "") - assert.Equal(t, "HubService", h.ServiceName()) -} - -func TestNewHubService_Good_GeneratesClientID(t *testing.T) { - h := testHubService(t, "") - id := h.GetClientID() - assert.NotEmpty(t, id) - // 16 bytes = 32 hex characters - assert.Len(t, id, 32) -} - -func TestNewHubService_Good_ReusesClientID(t *testing.T) { - cfg := testConfigService(t, nil, nil) - cfg.config.ClientID = "existing-client-id" - - h := NewHubService(cfg) - assert.Equal(t, "existing-client-id", h.GetClientID()) -} - -// ---- doRequest ---- - -func TestDoRequest_Good(t *testing.T) { - var gotAuth string - var gotContentType string - var gotAccept string - var gotBody map[string]string - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - gotAuth = r.Header.Get("Authorization") - gotContentType = r.Header.Get("Content-Type") - gotAccept = r.Header.Get("Accept") - - if r.Body != nil { - _ = json.NewDecoder(r.Body).Decode(&gotBody) - } - - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(`{"ok":true}`)) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "test-token-123" - h := NewHubService(cfg) - - body := map[string]string{"key": "value"} - resp, err := h.doRequest("POST", "/test", body) - require.NoError(t, err) - defer resp.Body.Close() - - assert.Equal(t, http.StatusOK, resp.StatusCode) - assert.Equal(t, "Bearer test-token-123", gotAuth) - assert.Equal(t, "application/json", gotContentType) - assert.Equal(t, "application/json", gotAccept) - assert.Equal(t, "value", gotBody["key"]) - assert.True(t, h.IsConnected()) -} - -func TestDoRequest_Bad_NoHubURL(t *testing.T) { - h := testHubService(t, "") - - resp, err := h.doRequest("GET", "/test", nil) - assert.Nil(t, resp) - assert.Error(t, err) - assert.Contains(t, err.Error(), "hub URL not configured") -} - -func TestDoRequest_Bad_NetworkError(t *testing.T) { - // Point to a port where nothing is listening. - h := testHubService(t, "http://127.0.0.1:1") - - resp, err := h.doRequest("GET", "/test", nil) - assert.Nil(t, resp) - assert.Error(t, err) - assert.False(t, h.IsConnected()) -} - -// ---- Task 4: AutoRegister ---- - -func TestAutoRegister_Good(t *testing.T) { - var gotBody map[string]string - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/auth/forge", r.URL.Path) - assert.Equal(t, "POST", r.Method) - - _ = json.NewDecoder(r.Body).Decode(&gotBody) - - w.WriteHeader(http.StatusCreated) - _, _ = w.Write([]byte(`{"api_key":"ak_test_12345"}`)) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.ForgeURL = "https://forge.example.com" - cfg.config.ForgeToken = "forge-tok-abc" - h := NewHubService(cfg) - - err := h.AutoRegister() - require.NoError(t, err) - - // Verify token was cached. - assert.Equal(t, "ak_test_12345", h.config.GetHubToken()) - - // Verify request body. - assert.Equal(t, "https://forge.example.com", gotBody["forge_url"]) - assert.Equal(t, "forge-tok-abc", gotBody["forge_token"]) - assert.NotEmpty(t, gotBody["client_id"]) -} - -func TestAutoRegister_Bad_NoForgeToken(t *testing.T) { - // Isolate from user's real ~/.core/config.yaml and env vars. - origHome := os.Getenv("HOME") - t.Setenv("HOME", t.TempDir()) - t.Setenv("FORGE_TOKEN", "") - t.Setenv("FORGE_URL", "") - defer os.Setenv("HOME", origHome) - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = "https://hub.example.com" - // No forge token set, and env/config are empty in test. - h := NewHubService(cfg) - - err := h.AutoRegister() - require.Error(t, err) - assert.Contains(t, err.Error(), "no forge token available") -} - -func TestAutoRegister_Good_SkipsIfAlreadyRegistered(t *testing.T) { - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = "https://hub.example.com" - cfg.config.HubToken = "existing-token" - h := NewHubService(cfg) - - err := h.AutoRegister() - require.NoError(t, err) - - // Token should remain unchanged. - assert.Equal(t, "existing-token", h.config.GetHubToken()) -} - -// ---- Task 5: Write Operations ---- - -func TestRegister_Good(t *testing.T) { - var gotPath string - var gotMethod string - var gotBody map[string]string - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - gotPath = r.URL.Path - gotMethod = r.Method - _ = json.NewDecoder(r.Body).Decode(&gotBody) - w.WriteHeader(http.StatusOK) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - cfg.config.ClientName = "MyBugSETI" - h := NewHubService(cfg) - - err := h.Register() - require.NoError(t, err) - assert.Equal(t, "/api/bugseti/register", gotPath) - assert.Equal(t, "POST", gotMethod) - assert.Equal(t, "MyBugSETI", gotBody["name"]) - assert.NotEmpty(t, gotBody["client_id"]) - assert.NotEmpty(t, gotBody["version"]) - assert.NotEmpty(t, gotBody["os"]) - assert.NotEmpty(t, gotBody["arch"]) -} - -func TestHeartbeat_Good(t *testing.T) { - var gotPath string - var gotMethod string - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - gotPath = r.URL.Path - gotMethod = r.Method - w.WriteHeader(http.StatusOK) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - err := h.Heartbeat() - require.NoError(t, err) - assert.Equal(t, "/api/bugseti/heartbeat", gotPath) - assert.Equal(t, "POST", gotMethod) -} - -func TestClaimIssue_Good(t *testing.T) { - now := time.Now().Truncate(time.Second) - expires := now.Add(30 * time.Minute) - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/issues/claim", r.URL.Path) - assert.Equal(t, "POST", r.Method) - - var body map[string]interface{} - _ = json.NewDecoder(r.Body).Decode(&body) - assert.Equal(t, "issue-42", body["issue_id"]) - assert.Equal(t, "org/repo", body["repo"]) - assert.Equal(t, float64(42), body["issue_number"]) - assert.Equal(t, "Fix the bug", body["title"]) - - w.WriteHeader(http.StatusOK) - resp := HubClaim{ - ID: "claim-1", - IssueURL: "https://github.com/org/repo/issues/42", - ClientID: "test", - ClaimedAt: now, - ExpiresAt: expires, - Status: "claimed", - } - _ = json.NewEncoder(w).Encode(resp) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - issue := &Issue{ - ID: "issue-42", - Number: 42, - Repo: "org/repo", - Title: "Fix the bug", - URL: "https://github.com/org/repo/issues/42", - } - - claim, err := h.ClaimIssue(issue) - require.NoError(t, err) - require.NotNil(t, claim) - assert.Equal(t, "claim-1", claim.ID) - assert.Equal(t, "claimed", claim.Status) -} - -func TestClaimIssue_Bad_Conflict(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusConflict) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - issue := &Issue{ID: "issue-99", Number: 99, Repo: "org/repo", Title: "Already claimed"} - - claim, err := h.ClaimIssue(issue) - assert.Nil(t, claim) - require.Error(t, err) - - var conflictErr *ConflictError - assert.ErrorAs(t, err, &conflictErr) -} - -func TestUpdateStatus_Good(t *testing.T) { - var gotPath string - var gotMethod string - var gotBody map[string]interface{} - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - gotPath = r.URL.Path - gotMethod = r.Method - _ = json.NewDecoder(r.Body).Decode(&gotBody) - w.WriteHeader(http.StatusOK) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - err := h.UpdateStatus("issue-42", "completed", "https://github.com/org/repo/pull/10", 10) - require.NoError(t, err) - assert.Equal(t, "PATCH", gotMethod) - assert.Equal(t, "/api/bugseti/issues/issue-42/status", gotPath) - assert.Equal(t, "completed", gotBody["status"]) - assert.Equal(t, "https://github.com/org/repo/pull/10", gotBody["pr_url"]) - assert.Equal(t, float64(10), gotBody["pr_number"]) -} - -func TestSyncStats_Good(t *testing.T) { - var gotBody map[string]interface{} - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/stats/sync", r.URL.Path) - assert.Equal(t, "POST", r.Method) - _ = json.NewDecoder(r.Body).Decode(&gotBody) - w.WriteHeader(http.StatusOK) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - stats := &Stats{ - IssuesAttempted: 10, - IssuesCompleted: 7, - IssuesSkipped: 3, - PRsSubmitted: 6, - PRsMerged: 5, - PRsRejected: 1, - CurrentStreak: 3, - LongestStreak: 5, - TotalTimeSpent: 90 * time.Minute, - ReposContributed: map[string]*RepoStats{ - "org/repo-a": {Name: "org/repo-a"}, - "org/repo-b": {Name: "org/repo-b"}, - }, - } - - err := h.SyncStats(stats) - require.NoError(t, err) - - assert.NotEmpty(t, gotBody["client_id"]) - statsMap, ok := gotBody["stats"].(map[string]interface{}) - require.True(t, ok) - assert.Equal(t, float64(10), statsMap["issues_attempted"]) - assert.Equal(t, float64(7), statsMap["issues_completed"]) - assert.Equal(t, float64(3), statsMap["issues_skipped"]) - assert.Equal(t, float64(6), statsMap["prs_submitted"]) - assert.Equal(t, float64(5), statsMap["prs_merged"]) - assert.Equal(t, float64(1), statsMap["prs_rejected"]) - assert.Equal(t, float64(3), statsMap["current_streak"]) - assert.Equal(t, float64(5), statsMap["longest_streak"]) - assert.Equal(t, float64(90), statsMap["total_time_minutes"]) - - reposRaw, ok := statsMap["repos_contributed"].([]interface{}) - require.True(t, ok) - assert.Len(t, reposRaw, 2) -} - -// ---- Task 6: Read Operations ---- - -func TestIsIssueClaimed_Good_Claimed(t *testing.T) { - now := time.Now().Truncate(time.Second) - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/issues/issue-42", r.URL.Path) - assert.Equal(t, "GET", r.Method) - - w.WriteHeader(http.StatusOK) - claim := HubClaim{ - ID: "claim-1", - IssueURL: "https://github.com/org/repo/issues/42", - ClientID: "client-abc", - ClaimedAt: now, - Status: "claimed", - } - _ = json.NewEncoder(w).Encode(claim) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - claim, err := h.IsIssueClaimed("issue-42") - require.NoError(t, err) - require.NotNil(t, claim) - assert.Equal(t, "claim-1", claim.ID) - assert.Equal(t, "claimed", claim.Status) -} - -func TestIsIssueClaimed_Good_NotClaimed(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - claim, err := h.IsIssueClaimed("issue-999") - assert.NoError(t, err) - assert.Nil(t, claim) -} - -func TestGetLeaderboard_Good(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/leaderboard", r.URL.Path) - assert.Equal(t, "GET", r.Method) - assert.Equal(t, "10", r.URL.Query().Get("limit")) - - resp := leaderboardResponse{ - Entries: []LeaderboardEntry{ - {ClientID: "a", ClientName: "Alice", Score: 100, PRsMerged: 10, Rank: 1}, - {ClientID: "b", ClientName: "Bob", Score: 80, PRsMerged: 8, Rank: 2}, - }, - TotalParticipants: 42, - } - w.WriteHeader(http.StatusOK) - _ = json.NewEncoder(w).Encode(resp) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - entries, total, err := h.GetLeaderboard(10) - require.NoError(t, err) - assert.Equal(t, 42, total) - require.Len(t, entries, 2) - assert.Equal(t, "Alice", entries[0].ClientName) - assert.Equal(t, 1, entries[0].Rank) - assert.Equal(t, "Bob", entries[1].ClientName) -} - -func TestGetGlobalStats_Good(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/api/bugseti/stats", r.URL.Path) - assert.Equal(t, "GET", r.Method) - - stats := GlobalStats{ - TotalClients: 100, - TotalClaims: 500, - TotalPRsMerged: 300, - ActiveClaims: 25, - IssuesAvailable: 150, - } - w.WriteHeader(http.StatusOK) - _ = json.NewEncoder(w).Encode(stats) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - stats, err := h.GetGlobalStats() - require.NoError(t, err) - require.NotNil(t, stats) - assert.Equal(t, 100, stats.TotalClients) - assert.Equal(t, 500, stats.TotalClaims) - assert.Equal(t, 300, stats.TotalPRsMerged) - assert.Equal(t, 25, stats.ActiveClaims) - assert.Equal(t, 150, stats.IssuesAvailable) -} - -// ---- Task 7: Pending Operations Queue ---- - -func TestPendingOps_Good_QueueAndDrain(t *testing.T) { - var callCount int32 - - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callCount++ - w.WriteHeader(http.StatusOK) - })) - defer srv.Close() - - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = srv.URL - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - // Manually queue a pending op (simulates a previous failed request). - h.queueOp("POST", "/heartbeat", map[string]string{"client_id": "test"}) - assert.Equal(t, 1, h.PendingCount()) - - // Register() calls drainPendingOps() first, then sends its own request. - err := h.Register() - require.NoError(t, err) - - // At least 2 calls: 1 from drain (the queued heartbeat) + 1 from Register itself. - assert.GreaterOrEqual(t, callCount, int32(2)) - assert.Equal(t, 0, h.PendingCount()) -} - -func TestPendingOps_Good_PersistAndLoad(t *testing.T) { - cfg1 := testConfigService(t, nil, nil) - cfg1.config.HubURL = "https://hub.example.com" - cfg1.config.HubToken = "tok" - h1 := NewHubService(cfg1) - - // Queue an op — this also calls savePendingOps. - h1.queueOp("POST", "/heartbeat", map[string]string{"client_id": "test"}) - assert.Equal(t, 1, h1.PendingCount()) - - // Create a second HubService with the same data dir. - // NewHubService calls loadPendingOps() in its constructor. - cfg2 := testConfigService(t, nil, nil) - cfg2.config.DataDir = cfg1.config.DataDir // Share the same data dir. - cfg2.config.HubURL = "https://hub.example.com" - cfg2.config.HubToken = "tok" - h2 := NewHubService(cfg2) - - assert.Equal(t, 1, h2.PendingCount()) -} - -func TestPendingCount_Good(t *testing.T) { - cfg := testConfigService(t, nil, nil) - cfg.config.HubURL = "https://hub.example.com" - cfg.config.HubToken = "tok" - h := NewHubService(cfg) - - assert.Equal(t, 0, h.PendingCount()) - - h.queueOp("POST", "/test1", nil) - assert.Equal(t, 1, h.PendingCount()) - - h.queueOp("POST", "/test2", map[string]string{"key": "val"}) - assert.Equal(t, 2, h.PendingCount()) -} diff --git a/internal/bugseti/mcp_marketplace.go b/internal/bugseti/mcp_marketplace.go deleted file mode 100644 index 9f379dfd..00000000 --- a/internal/bugseti/mcp_marketplace.go +++ /dev/null @@ -1,246 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - "strings" - "time" - - "github.com/mark3labs/mcp-go/client" - "github.com/mark3labs/mcp-go/mcp" -) - -type Marketplace struct { - Schema string `json:"$schema,omitempty"` - Name string `json:"name"` - Description string `json:"description"` - Owner MarketplaceOwner `json:"owner"` - Plugins []MarketplacePlugin `json:"plugins"` -} - -type MarketplaceOwner struct { - Name string `json:"name"` - Email string `json:"email"` -} - -type MarketplacePlugin struct { - Name string `json:"name"` - Description string `json:"description"` - Version string `json:"version"` - Source string `json:"source"` - Category string `json:"category"` -} - -type PluginInfo struct { - Plugin MarketplacePlugin `json:"plugin"` - Path string `json:"path"` - Manifest map[string]any `json:"manifest,omitempty"` - Commands []string `json:"commands,omitempty"` - Skills []string `json:"skills,omitempty"` -} - -type EthicsContext struct { - Modal string `json:"modal"` - Axioms map[string]any `json:"axioms"` -} - -type marketplaceClient interface { - ListMarketplace(ctx context.Context) ([]MarketplacePlugin, error) - PluginInfo(ctx context.Context, name string) (*PluginInfo, error) - EthicsCheck(ctx context.Context) (*EthicsContext, error) - Close() error -} - -type mcpMarketplaceClient struct { - client *client.Client -} - -func newMarketplaceClient(ctx context.Context, rootHint string) (marketplaceClient, error) { - if ctx == nil { - ctx = context.Background() - } - - command, args, err := resolveMarketplaceCommand(rootHint) - if err != nil { - return nil, err - } - - mcpClient, err := client.NewStdioMCPClient(command, nil, args...) - if err != nil { - return nil, fmt.Errorf("failed to start marketplace MCP client: %w", err) - } - - initRequest := mcp.InitializeRequest{} - initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION - initRequest.Params.ClientInfo = mcp.Implementation{ - Name: "bugseti", - Version: GetVersion(), - } - - initCtx, cancel := context.WithTimeout(ctx, 10*time.Second) - defer cancel() - if _, err := mcpClient.Initialize(initCtx, initRequest); err != nil { - _ = mcpClient.Close() - return nil, fmt.Errorf("failed to initialize marketplace MCP client: %w", err) - } - - return &mcpMarketplaceClient{client: mcpClient}, nil -} - -func (c *mcpMarketplaceClient) Close() error { - if c == nil || c.client == nil { - return nil - } - return c.client.Close() -} - -func (c *mcpMarketplaceClient) ListMarketplace(ctx context.Context) ([]MarketplacePlugin, error) { - var marketplace Marketplace - if err := c.callToolStructured(ctx, "marketplace_list", nil, &marketplace); err != nil { - return nil, err - } - return marketplace.Plugins, nil -} - -func (c *mcpMarketplaceClient) PluginInfo(ctx context.Context, name string) (*PluginInfo, error) { - var info PluginInfo - args := map[string]any{"name": name} - if err := c.callToolStructured(ctx, "marketplace_plugin_info", args, &info); err != nil { - return nil, err - } - return &info, nil -} - -func (c *mcpMarketplaceClient) EthicsCheck(ctx context.Context) (*EthicsContext, error) { - var ethics EthicsContext - if err := c.callToolStructured(ctx, "ethics_check", nil, ðics); err != nil { - return nil, err - } - return ðics, nil -} - -func (c *mcpMarketplaceClient) callToolStructured(ctx context.Context, name string, args map[string]any, target any) error { - if c == nil || c.client == nil { - return errors.New("marketplace client is not initialized") - } - if ctx == nil { - ctx = context.Background() - } - - request := mcp.CallToolRequest{} - request.Params.Name = name - if args != nil { - request.Params.Arguments = args - } - - result, err := c.client.CallTool(ctx, request) - if err != nil { - return err - } - if result == nil { - return errors.New("marketplace tool returned no result") - } - if result.IsError { - return fmt.Errorf("marketplace tool %s error: %s", name, toolResultMessage(result)) - } - if result.StructuredContent == nil { - return fmt.Errorf("marketplace tool %s returned no structured content", name) - } - payload, err := json.Marshal(result.StructuredContent) - if err != nil { - return fmt.Errorf("failed to encode marketplace response: %w", err) - } - if err := json.Unmarshal(payload, target); err != nil { - return fmt.Errorf("failed to decode marketplace response: %w", err) - } - return nil -} - -func toolResultMessage(result *mcp.CallToolResult) string { - if result == nil { - return "unknown error" - } - for _, content := range result.Content { - switch value := content.(type) { - case mcp.TextContent: - if value.Text != "" { - return value.Text - } - case *mcp.TextContent: - if value != nil && value.Text != "" { - return value.Text - } - } - } - return "unknown error" -} - -func resolveMarketplaceCommand(rootHint string) (string, []string, error) { - if command := strings.TrimSpace(os.Getenv("BUGSETI_MCP_COMMAND")); command != "" { - args := strings.Fields(os.Getenv("BUGSETI_MCP_ARGS")) - return command, args, nil - } - - if root := strings.TrimSpace(rootHint); root != "" { - path := filepath.Join(root, "mcp") - return "go", []string{"run", path}, nil - } - - if root := strings.TrimSpace(os.Getenv("BUGSETI_MCP_ROOT")); root != "" { - path := filepath.Join(root, "mcp") - return "go", []string{"run", path}, nil - } - - if root, ok := findCoreAgentRoot(); ok { - return "go", []string{"run", filepath.Join(root, "mcp")}, nil - } - - return "", nil, fmt.Errorf("marketplace MCP server not configured (set BUGSETI_MCP_COMMAND or BUGSETI_MCP_ROOT)") -} - -func findCoreAgentRoot() (string, bool) { - var candidates []string - if cwd, err := os.Getwd(); err == nil { - candidates = append(candidates, cwd) - candidates = append(candidates, filepath.Dir(cwd)) - } - if exe, err := os.Executable(); err == nil { - exeDir := filepath.Dir(exe) - candidates = append(candidates, exeDir) - candidates = append(candidates, filepath.Dir(exeDir)) - } - - seen := make(map[string]bool) - for _, base := range candidates { - base = filepath.Clean(base) - if seen[base] { - continue - } - seen[base] = true - - root := filepath.Join(base, "core-agent") - if hasMcpDir(root) { - return root, true - } - - root = filepath.Join(base, "..", "core-agent") - if hasMcpDir(root) { - return filepath.Clean(root), true - } - } - - return "", false -} - -func hasMcpDir(root string) bool { - if root == "" { - return false - } - info, err := os.Stat(filepath.Join(root, "mcp", "main.go")) - return err == nil && !info.IsDir() -} diff --git a/internal/bugseti/notify.go b/internal/bugseti/notify.go deleted file mode 100644 index c467c1b2..00000000 --- a/internal/bugseti/notify.go +++ /dev/null @@ -1,252 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "context" - "fmt" - "log" - "os/exec" - "runtime" - "time" -) - -// NotifyService handles desktop notifications. -type NotifyService struct { - enabled bool - sound bool - config *ConfigService -} - -// NewNotifyService creates a new NotifyService. -func NewNotifyService(config *ConfigService) *NotifyService { - return &NotifyService{ - enabled: true, - sound: true, - config: config, - } -} - -// ServiceName returns the service name for Wails. -func (n *NotifyService) ServiceName() string { - return "NotifyService" -} - -// SetEnabled enables or disables notifications. -func (n *NotifyService) SetEnabled(enabled bool) { - n.enabled = enabled -} - -// SetSound enables or disables notification sounds. -func (n *NotifyService) SetSound(sound bool) { - n.sound = sound -} - -// Notify sends a desktop notification. -func (n *NotifyService) Notify(title, message string) error { - if !n.enabled { - return nil - } - - guard := getEthicsGuardWithRoot(context.Background(), n.getMarketplaceRoot()) - safeTitle := guard.SanitizeNotification(title) - safeMessage := guard.SanitizeNotification(message) - - log.Printf("Notification: %s - %s", safeTitle, safeMessage) - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - var err error - switch runtime.GOOS { - case "darwin": - err = n.notifyMacOS(ctx, safeTitle, safeMessage) - case "linux": - err = n.notifyLinux(ctx, safeTitle, safeMessage) - case "windows": - err = n.notifyWindows(ctx, safeTitle, safeMessage) - default: - err = fmt.Errorf("unsupported platform: %s", runtime.GOOS) - } - - if err != nil { - log.Printf("Notification error: %v", err) - } - return err -} - -func (n *NotifyService) getMarketplaceRoot() string { - if n == nil || n.config == nil { - return "" - } - return n.config.GetMarketplaceMCPRoot() -} - -// NotifyIssue sends a notification about a new issue. -func (n *NotifyService) NotifyIssue(issue *Issue) error { - title := "New Issue Available" - message := fmt.Sprintf("%s: %s", issue.Repo, issue.Title) - return n.Notify(title, message) -} - -// NotifyPRStatus sends a notification about a PR status change. -func (n *NotifyService) NotifyPRStatus(repo string, prNumber int, status string) error { - title := "PR Status Update" - message := fmt.Sprintf("%s #%d: %s", repo, prNumber, status) - return n.Notify(title, message) -} - -// notifyMacOS sends a notification on macOS using osascript. -func (n *NotifyService) notifyMacOS(ctx context.Context, title, message string) error { - script := fmt.Sprintf(`display notification "%s" with title "%s"`, escapeAppleScript(message), escapeAppleScript(title)) - if n.sound { - script += ` sound name "Glass"` - } - cmd := exec.CommandContext(ctx, "osascript", "-e", script) - return cmd.Run() -} - -// notifyLinux sends a notification on Linux using notify-send. -func (n *NotifyService) notifyLinux(ctx context.Context, title, message string) error { - args := []string{ - "--app-name=BugSETI", - "--urgency=normal", - title, - message, - } - cmd := exec.CommandContext(ctx, "notify-send", args...) - return cmd.Run() -} - -// notifyWindows sends a notification on Windows using PowerShell. -func (n *NotifyService) notifyWindows(ctx context.Context, title, message string) error { - title = escapePowerShellXML(title) - message = escapePowerShellXML(message) - - script := fmt.Sprintf(` -[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null -[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null - -$template = @" - - - - %s - %s - - - -"@ - -$xml = New-Object Windows.Data.Xml.Dom.XmlDocument -$xml.LoadXml($template) -$toast = [Windows.UI.Notifications.ToastNotification]::new($xml) -[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("BugSETI").Show($toast) -`, title, message) - - cmd := exec.CommandContext(ctx, "powershell", "-Command", script) - return cmd.Run() -} - -// NotifyWithAction sends a notification with an action button (platform-specific). -func (n *NotifyService) NotifyWithAction(title, message, actionLabel string) error { - if !n.enabled { - return nil - } - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - switch runtime.GOOS { - case "darwin": - // macOS: Use terminal-notifier if available for actions - if _, err := exec.LookPath("terminal-notifier"); err == nil { - cmd := exec.CommandContext(ctx, "terminal-notifier", - "-title", title, - "-message", message, - "-appIcon", "NSApplication", - "-actions", actionLabel, - "-group", "BugSETI") - return cmd.Run() - } - return n.notifyMacOS(ctx, title, message) - - case "linux": - // Linux: Use notify-send with action - args := []string{ - "--app-name=BugSETI", - "--urgency=normal", - "--action=open=" + actionLabel, - title, - message, - } - cmd := exec.CommandContext(ctx, "notify-send", args...) - return cmd.Run() - - default: - return n.Notify(title, message) - } -} - -// NotifyProgress sends a notification with a progress indicator. -func (n *NotifyService) NotifyProgress(title, message string, progress int) error { - if !n.enabled { - return nil - } - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - switch runtime.GOOS { - case "linux": - // Linux supports progress hints - args := []string{ - "--app-name=BugSETI", - "--hint=int:value:" + fmt.Sprintf("%d", progress), - title, - message, - } - cmd := exec.CommandContext(ctx, "notify-send", args...) - return cmd.Run() - - default: - // Other platforms: include progress in message - messageWithProgress := fmt.Sprintf("%s (%d%%)", message, progress) - return n.Notify(title, messageWithProgress) - } -} - -// PlaySound plays a notification sound. -func (n *NotifyService) PlaySound() error { - if !n.sound { - return nil - } - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - switch runtime.GOOS { - case "darwin": - cmd := exec.CommandContext(ctx, "afplay", "/System/Library/Sounds/Glass.aiff") - return cmd.Run() - - case "linux": - // Try paplay (PulseAudio), then aplay (ALSA) - if _, err := exec.LookPath("paplay"); err == nil { - cmd := exec.CommandContext(ctx, "paplay", "/usr/share/sounds/freedesktop/stereo/complete.oga") - return cmd.Run() - } - if _, err := exec.LookPath("aplay"); err == nil { - cmd := exec.CommandContext(ctx, "aplay", "-q", "/usr/share/sounds/alsa/Front_Center.wav") - return cmd.Run() - } - return nil - - case "windows": - script := `[console]::beep(800, 200)` - cmd := exec.CommandContext(ctx, "powershell", "-Command", script) - return cmd.Run() - - default: - return nil - } -} diff --git a/internal/bugseti/queue.go b/internal/bugseti/queue.go deleted file mode 100644 index 6b06d5ca..00000000 --- a/internal/bugseti/queue.go +++ /dev/null @@ -1,314 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "container/heap" - "encoding/json" - "log" - "os" - "path/filepath" - "sync" - "time" -) - -// IssueStatus represents the status of an issue in the queue. -type IssueStatus string - -const ( - StatusPending IssueStatus = "pending" - StatusClaimed IssueStatus = "claimed" - StatusInProgress IssueStatus = "in_progress" - StatusCompleted IssueStatus = "completed" - StatusSkipped IssueStatus = "skipped" -) - -// Issue represents a GitHub issue in the queue. -type Issue struct { - ID string `json:"id"` - Number int `json:"number"` - Repo string `json:"repo"` - Title string `json:"title"` - Body string `json:"body"` - URL string `json:"url"` - Labels []string `json:"labels"` - Author string `json:"author"` - CreatedAt time.Time `json:"createdAt"` - Priority int `json:"priority"` - Status IssueStatus `json:"status"` - ClaimedAt time.Time `json:"claimedAt,omitempty"` - Context *IssueContext `json:"context,omitempty"` - Comments []Comment `json:"comments,omitempty"` - index int // For heap interface -} - -// Comment represents a comment on an issue. -type Comment struct { - Author string `json:"author"` - Body string `json:"body"` -} - -// IssueContext contains AI-prepared context for an issue. -type IssueContext struct { - Summary string `json:"summary"` - RelevantFiles []string `json:"relevantFiles"` - SuggestedFix string `json:"suggestedFix"` - RelatedIssues []string `json:"relatedIssues"` - Complexity string `json:"complexity"` - EstimatedTime string `json:"estimatedTime"` - PreparedAt time.Time `json:"preparedAt"` -} - -// QueueService manages the priority queue of issues. -type QueueService struct { - config *ConfigService - issues issueHeap - seen map[string]bool - current *Issue - mu sync.RWMutex -} - -// issueHeap implements heap.Interface for priority queue. -type issueHeap []*Issue - -func (h issueHeap) Len() int { return len(h) } -func (h issueHeap) Less(i, j int) bool { return h[i].Priority > h[j].Priority } // Higher priority first -func (h issueHeap) Swap(i, j int) { - h[i], h[j] = h[j], h[i] - h[i].index = i - h[j].index = j -} - -func (h *issueHeap) Push(x any) { - n := len(*h) - item := x.(*Issue) - item.index = n - *h = append(*h, item) -} - -func (h *issueHeap) Pop() any { - old := *h - n := len(old) - item := old[n-1] - old[n-1] = nil - item.index = -1 - *h = old[0 : n-1] - return item -} - -// NewQueueService creates a new QueueService. -func NewQueueService(config *ConfigService) *QueueService { - q := &QueueService{ - config: config, - } - - // Hold the lock for the entire initialization sequence so that all - // shared state (issues, seen, current) is fully populated before - // any concurrent caller can observe the service. - q.mu.Lock() - defer q.mu.Unlock() - - q.issues = make(issueHeap, 0) - q.seen = make(map[string]bool) - q.load() // Load persisted queue (overwrites issues/seen if file exists) - return q -} - -// ServiceName returns the service name for Wails. -func (q *QueueService) ServiceName() string { - return "QueueService" -} - -// Add adds issues to the queue, deduplicating by ID. -func (q *QueueService) Add(issues []*Issue) int { - q.mu.Lock() - defer q.mu.Unlock() - - added := 0 - for _, issue := range issues { - if q.seen[issue.ID] { - continue - } - q.seen[issue.ID] = true - issue.Status = StatusPending - heap.Push(&q.issues, issue) - added++ - } - - if added > 0 { - q.save() - } - return added -} - -// Size returns the number of issues in the queue. -func (q *QueueService) Size() int { - q.mu.RLock() - defer q.mu.RUnlock() - return len(q.issues) -} - -// CurrentIssue returns the issue currently being worked on. -func (q *QueueService) CurrentIssue() *Issue { - q.mu.RLock() - defer q.mu.RUnlock() - return q.current -} - -// Next claims and returns the next issue from the queue. -func (q *QueueService) Next() *Issue { - q.mu.Lock() - defer q.mu.Unlock() - - if len(q.issues) == 0 { - return nil - } - - // Pop the highest priority issue - issue := heap.Pop(&q.issues).(*Issue) - issue.Status = StatusClaimed - issue.ClaimedAt = time.Now() - q.current = issue - q.save() - return issue -} - -// Skip marks the current issue as skipped and moves to the next. -func (q *QueueService) Skip() { - q.mu.Lock() - defer q.mu.Unlock() - - if q.current != nil { - q.current.Status = StatusSkipped - q.current = nil - q.save() - } -} - -// Complete marks the current issue as completed. -func (q *QueueService) Complete() { - q.mu.Lock() - defer q.mu.Unlock() - - if q.current != nil { - q.current.Status = StatusCompleted - q.current = nil - q.save() - } -} - -// SetInProgress marks the current issue as in progress. -func (q *QueueService) SetInProgress() { - q.mu.Lock() - defer q.mu.Unlock() - - if q.current != nil { - q.current.Status = StatusInProgress - q.save() - } -} - -// SetContext sets the AI-prepared context for the current issue. -func (q *QueueService) SetContext(ctx *IssueContext) { - q.mu.Lock() - defer q.mu.Unlock() - - if q.current != nil { - q.current.Context = ctx - q.save() - } -} - -// GetPending returns all pending issues. -func (q *QueueService) GetPending() []*Issue { - q.mu.RLock() - defer q.mu.RUnlock() - - result := make([]*Issue, 0, len(q.issues)) - for _, issue := range q.issues { - if issue.Status == StatusPending { - result = append(result, issue) - } - } - return result -} - -// Clear removes all issues from the queue. -func (q *QueueService) Clear() { - q.mu.Lock() - defer q.mu.Unlock() - - q.issues = make(issueHeap, 0) - q.seen = make(map[string]bool) - q.current = nil - heap.Init(&q.issues) - q.save() -} - -// queueState represents the persisted queue state. -type queueState struct { - Issues []*Issue `json:"issues"` - Current *Issue `json:"current"` - Seen []string `json:"seen"` -} - -// save persists the queue to disk. Must be called with q.mu held. -func (q *QueueService) save() { - dataDir := q.config.GetDataDir() - if dataDir == "" { - return - } - - path := filepath.Join(dataDir, "queue.json") - - seen := make([]string, 0, len(q.seen)) - for id := range q.seen { - seen = append(seen, id) - } - - state := queueState{ - Issues: []*Issue(q.issues), - Current: q.current, - Seen: seen, - } - - data, err := json.MarshalIndent(state, "", " ") - if err != nil { - log.Printf("Failed to marshal queue: %v", err) - return - } - - if err := os.WriteFile(path, data, 0644); err != nil { - log.Printf("Failed to save queue: %v", err) - } -} - -// load restores the queue from disk. Must be called with q.mu held. -func (q *QueueService) load() { - dataDir := q.config.GetDataDir() - if dataDir == "" { - return - } - - path := filepath.Join(dataDir, "queue.json") - data, err := os.ReadFile(path) - if err != nil { - if !os.IsNotExist(err) { - log.Printf("Failed to read queue: %v", err) - } - return - } - - var state queueState - if err := json.Unmarshal(data, &state); err != nil { - log.Printf("Failed to unmarshal queue: %v", err) - return - } - - q.issues = state.Issues - heap.Init(&q.issues) - q.current = state.Current - q.seen = make(map[string]bool) - for _, id := range state.Seen { - q.seen[id] = true - } -} diff --git a/internal/bugseti/seeder.go b/internal/bugseti/seeder.go deleted file mode 100644 index 50195148..00000000 --- a/internal/bugseti/seeder.go +++ /dev/null @@ -1,383 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "sync" - "time" -) - -// SeederService prepares context for issues using the seed-agent-developer skill. -type SeederService struct { - mu sync.Mutex - config *ConfigService - forgeURL string - forgeToken string -} - -// NewSeederService creates a new SeederService. -func NewSeederService(config *ConfigService, forgeURL, forgeToken string) *SeederService { - return &SeederService{ - config: config, - forgeURL: forgeURL, - forgeToken: forgeToken, - } -} - -// ServiceName returns the service name for Wails. -func (s *SeederService) ServiceName() string { - return "SeederService" -} - -// SeedIssue prepares context for an issue by calling the seed-agent-developer skill. -func (s *SeederService) SeedIssue(issue *Issue) (*IssueContext, error) { - s.mu.Lock() - defer s.mu.Unlock() - - if issue == nil { - return nil, fmt.Errorf("issue is nil") - } - - // Create a temporary workspace for the issue - workDir, err := s.prepareWorkspace(issue) - if err != nil { - return nil, fmt.Errorf("failed to prepare workspace: %w", err) - } - - // Try to use the seed-agent-developer skill via plugin system - ctx, err := s.runSeedSkill(issue, workDir) - if err != nil { - log.Printf("Seed skill failed, using fallback: %v", err) - // Fallback to basic context preparation - guard := getEthicsGuardWithRoot(context.Background(), s.config.GetMarketplaceMCPRoot()) - ctx = s.prepareBasicContext(issue, guard) - } - - ctx.PreparedAt = time.Now() - return ctx, nil -} - -// prepareWorkspace creates a temporary workspace and clones the repo. -func (s *SeederService) prepareWorkspace(issue *Issue) (string, error) { - // Create workspace directory - baseDir := s.config.GetWorkspaceDir() - if baseDir == "" { - baseDir = filepath.Join(os.TempDir(), "bugseti") - } - - // Create issue-specific directory - workDir := filepath.Join(baseDir, sanitizeRepoName(issue.Repo), fmt.Sprintf("issue-%d", issue.Number)) - if err := os.MkdirAll(workDir, 0755); err != nil { - return "", fmt.Errorf("failed to create workspace: %w", err) - } - - // Check if repo already cloned - if _, err := os.Stat(filepath.Join(workDir, ".git")); os.IsNotExist(err) { - // Clone the repository - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) - defer cancel() - - cloneURL := fmt.Sprintf("%s/%s.git", strings.TrimRight(s.forgeURL, "/"), issue.Repo) - cmd := exec.CommandContext(ctx, "git", "clone", "--depth=1", cloneURL, workDir) - cmd.Env = append(os.Environ(), - fmt.Sprintf("GIT_ASKPASS=echo"), - fmt.Sprintf("GIT_TERMINAL_PROMPT=0"), - ) - if s.forgeToken != "" { - // Use token auth via URL for HTTPS clones - cloneURL = fmt.Sprintf("%s/%s.git", strings.TrimRight(s.forgeURL, "/"), issue.Repo) - cloneURL = strings.Replace(cloneURL, "://", fmt.Sprintf("://bugseti:%s@", s.forgeToken), 1) - cmd = exec.CommandContext(ctx, "git", "clone", "--depth=1", cloneURL, workDir) - } - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return "", fmt.Errorf("failed to clone repo: %s: %w", stderr.String(), err) - } - } - - return workDir, nil -} - -// runSeedSkill executes the seed-agent-developer skill to prepare context. -func (s *SeederService) runSeedSkill(issue *Issue, workDir string) (*IssueContext, error) { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - mcpCtx, mcpCancel := context.WithTimeout(ctx, 20*time.Second) - defer mcpCancel() - - marketplace, err := newMarketplaceClient(mcpCtx, s.config.GetMarketplaceMCPRoot()) - if err != nil { - return nil, err - } - defer marketplace.Close() - - guard := guardFromMarketplace(mcpCtx, marketplace) - - scriptPath, err := findSeedSkillScript(mcpCtx, marketplace) - if err != nil { - return nil, err - } - - // Run the analyze-issue script - cmd := exec.CommandContext(ctx, "bash", scriptPath) - cmd.Dir = workDir - cmd.Env = append(os.Environ(), - fmt.Sprintf("ISSUE_NUMBER=%d", issue.Number), - fmt.Sprintf("ISSUE_REPO=%s", guard.SanitizeEnv(issue.Repo)), - fmt.Sprintf("ISSUE_TITLE=%s", guard.SanitizeEnv(issue.Title)), - fmt.Sprintf("ISSUE_URL=%s", guard.SanitizeEnv(issue.URL)), - ) - - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - - if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("seed skill failed: %s: %w", stderr.String(), err) - } - - // Parse the output as JSON - var result struct { - Summary string `json:"summary"` - RelevantFiles []string `json:"relevant_files"` - SuggestedFix string `json:"suggested_fix"` - RelatedIssues []string `json:"related_issues"` - Complexity string `json:"complexity"` - EstimatedTime string `json:"estimated_time"` - } - - if err := json.Unmarshal(stdout.Bytes(), &result); err != nil { - // If not JSON, treat as plain text summary - return sanitizeIssueContext(&IssueContext{ - Summary: stdout.String(), - Complexity: "unknown", - }, guard), nil - } - - return sanitizeIssueContext(&IssueContext{ - Summary: result.Summary, - RelevantFiles: result.RelevantFiles, - SuggestedFix: result.SuggestedFix, - RelatedIssues: result.RelatedIssues, - Complexity: result.Complexity, - EstimatedTime: result.EstimatedTime, - }, guard), nil -} - -// prepareBasicContext creates a basic context without the seed skill. -func (s *SeederService) prepareBasicContext(issue *Issue, guard *EthicsGuard) *IssueContext { - // Extract potential file references from issue body - files := extractFileReferences(issue.Body) - - // Estimate complexity based on labels and body length - complexity := estimateComplexity(issue) - - return sanitizeIssueContext(&IssueContext{ - Summary: fmt.Sprintf("Issue #%d in %s: %s", issue.Number, issue.Repo, issue.Title), - RelevantFiles: files, - Complexity: complexity, - EstimatedTime: estimateTime(complexity), - }, guard) -} - -// sanitizeRepoName converts owner/repo to a safe directory name. -func sanitizeRepoName(repo string) string { - return strings.ReplaceAll(repo, "/", "-") -} - -// extractFileReferences finds file paths mentioned in text. -func extractFileReferences(text string) []string { - var files []string - seen := make(map[string]bool) - - // Common file patterns - patterns := []string{ - `.go`, `.js`, `.ts`, `.py`, `.rs`, `.java`, `.cpp`, `.c`, `.h`, - `.json`, `.yaml`, `.yml`, `.toml`, `.xml`, `.md`, - } - - words := strings.Fields(text) - for _, word := range words { - // Clean up the word - word = strings.Trim(word, "`,\"'()[]{}:") - - // Check if it looks like a file path - for _, ext := range patterns { - if strings.HasSuffix(word, ext) && !seen[word] { - files = append(files, word) - seen[word] = true - break - } - } - } - - return files -} - -// estimateComplexity guesses issue complexity from content. -func estimateComplexity(issue *Issue) string { - bodyLen := len(issue.Body) - labelScore := 0 - - for _, label := range issue.Labels { - lower := strings.ToLower(label) - switch { - case strings.Contains(lower, "good first issue"), strings.Contains(lower, "beginner"): - labelScore -= 2 - case strings.Contains(lower, "easy"): - labelScore -= 1 - case strings.Contains(lower, "complex"), strings.Contains(lower, "hard"): - labelScore += 2 - case strings.Contains(lower, "refactor"): - labelScore += 1 - } - } - - // Combine body length and label score - score := labelScore - if bodyLen > 2000 { - score += 2 - } else if bodyLen > 500 { - score += 1 - } - - switch { - case score <= -1: - return "easy" - case score <= 1: - return "medium" - default: - return "hard" - } -} - -// estimateTime suggests time based on complexity. -func estimateTime(complexity string) string { - switch complexity { - case "easy": - return "15-30 minutes" - case "medium": - return "1-2 hours" - case "hard": - return "2-4 hours" - default: - return "unknown" - } -} - -const seedSkillName = "seed-agent-developer" - -func findSeedSkillScript(ctx context.Context, marketplace marketplaceClient) (string, error) { - if marketplace == nil { - return "", fmt.Errorf("marketplace client is nil") - } - - plugins, err := marketplace.ListMarketplace(ctx) - if err != nil { - return "", err - } - - for _, plugin := range plugins { - info, err := marketplace.PluginInfo(ctx, plugin.Name) - if err != nil || info == nil { - continue - } - - if !containsSkill(info.Skills, seedSkillName) { - continue - } - - scriptPath, err := safeJoinUnder(info.Path, "skills", seedSkillName, "scripts", "analyze-issue.sh") - if err != nil { - continue - } - if stat, err := os.Stat(scriptPath); err == nil && !stat.IsDir() { - return scriptPath, nil - } - } - - return "", fmt.Errorf("seed-agent-developer skill not found in marketplace") -} - -func containsSkill(skills []string, name string) bool { - for _, skill := range skills { - if skill == name { - return true - } - } - return false -} - -func safeJoinUnder(base string, elems ...string) (string, error) { - if base == "" { - return "", fmt.Errorf("base path is empty") - } - baseAbs, err := filepath.Abs(base) - if err != nil { - return "", fmt.Errorf("failed to resolve base path: %w", err) - } - - joined := filepath.Join(append([]string{baseAbs}, elems...)...) - rel, err := filepath.Rel(baseAbs, joined) - if err != nil { - return "", fmt.Errorf("failed to resolve relative path: %w", err) - } - if strings.HasPrefix(rel, "..") { - return "", fmt.Errorf("resolved path escapes base: %s", rel) - } - - return joined, nil -} - -func sanitizeIssueContext(ctx *IssueContext, guard *EthicsGuard) *IssueContext { - if ctx == nil { - return nil - } - if guard == nil { - guard = &EthicsGuard{} - } - - ctx.Summary = guard.SanitizeSummary(ctx.Summary) - ctx.SuggestedFix = guard.SanitizeSummary(ctx.SuggestedFix) - ctx.Complexity = guard.SanitizeTitle(ctx.Complexity) - ctx.EstimatedTime = guard.SanitizeTitle(ctx.EstimatedTime) - ctx.RelatedIssues = guard.SanitizeList(ctx.RelatedIssues, maxTitleRunes) - ctx.RelevantFiles = guard.SanitizeFiles(ctx.RelevantFiles) - return ctx -} - -// GetWorkspaceDir returns the workspace directory for an issue. -func (s *SeederService) GetWorkspaceDir(issue *Issue) string { - s.mu.Lock() - defer s.mu.Unlock() - - return s.getWorkspaceDir(issue) -} - -// getWorkspaceDir is the lock-free implementation; caller must hold s.mu. -func (s *SeederService) getWorkspaceDir(issue *Issue) string { - baseDir := s.config.GetWorkspaceDir() - if baseDir == "" { - baseDir = filepath.Join(os.TempDir(), "bugseti") - } - return filepath.Join(baseDir, sanitizeRepoName(issue.Repo), fmt.Sprintf("issue-%d", issue.Number)) -} - -// CleanupWorkspace removes the workspace for an issue. -func (s *SeederService) CleanupWorkspace(issue *Issue) error { - s.mu.Lock() - defer s.mu.Unlock() - - workDir := s.getWorkspaceDir(issue) - return os.RemoveAll(workDir) -} diff --git a/internal/bugseti/seeder_test.go b/internal/bugseti/seeder_test.go deleted file mode 100644 index daef6591..00000000 --- a/internal/bugseti/seeder_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package bugseti - -import ( - "context" - "fmt" - "os" - "path/filepath" - "testing" -) - -type fakeMarketplaceClient struct { - plugins []MarketplacePlugin - infos map[string]*PluginInfo - listErr error - infoErr map[string]error -} - -func (f *fakeMarketplaceClient) ListMarketplace(ctx context.Context) ([]MarketplacePlugin, error) { - if f.listErr != nil { - return nil, f.listErr - } - return f.plugins, nil -} - -func (f *fakeMarketplaceClient) PluginInfo(ctx context.Context, name string) (*PluginInfo, error) { - if err, ok := f.infoErr[name]; ok { - return nil, err - } - info, ok := f.infos[name] - if !ok { - return nil, fmt.Errorf("plugin not found") - } - return info, nil -} - -func (f *fakeMarketplaceClient) EthicsCheck(ctx context.Context) (*EthicsContext, error) { - return nil, fmt.Errorf("not implemented") -} - -func (f *fakeMarketplaceClient) Close() error { - return nil -} - -func TestFindSeedSkillScript_Good(t *testing.T) { - root := t.TempDir() - scriptPath := filepath.Join(root, "skills", seedSkillName, "scripts", "analyze-issue.sh") - if err := os.MkdirAll(filepath.Dir(scriptPath), 0755); err != nil { - t.Fatalf("failed to create script directory: %v", err) - } - if err := os.WriteFile(scriptPath, []byte("#!/bin/bash\n"), 0755); err != nil { - t.Fatalf("failed to write script: %v", err) - } - - plugin := MarketplacePlugin{Name: "seed-plugin"} - client := &fakeMarketplaceClient{ - plugins: []MarketplacePlugin{plugin}, - infos: map[string]*PluginInfo{ - plugin.Name: { - Plugin: plugin, - Path: root, - Skills: []string{seedSkillName}, - }, - }, - } - - found, err := findSeedSkillScript(context.Background(), client) - if err != nil { - t.Fatalf("expected script path, got error: %v", err) - } - if found != scriptPath { - t.Fatalf("expected %q, got %q", scriptPath, found) - } -} - -func TestFindSeedSkillScript_Bad(t *testing.T) { - plugin := MarketplacePlugin{Name: "empty-plugin"} - client := &fakeMarketplaceClient{ - plugins: []MarketplacePlugin{plugin}, - infos: map[string]*PluginInfo{ - plugin.Name: { - Plugin: plugin, - Path: t.TempDir(), - Skills: []string{"not-the-skill"}, - }, - }, - } - - if _, err := findSeedSkillScript(context.Background(), client); err == nil { - t.Fatal("expected error when skill is missing") - } -} - -func TestSafeJoinUnder_Ugly(t *testing.T) { - if _, err := safeJoinUnder("", "skills"); err == nil { - t.Fatal("expected error for empty base path") - } -} diff --git a/internal/bugseti/stats.go b/internal/bugseti/stats.go deleted file mode 100644 index f8bc2672..00000000 --- a/internal/bugseti/stats.go +++ /dev/null @@ -1,359 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "encoding/json" - "log" - "os" - "path/filepath" - "sync" - "time" -) - -// StatsService tracks user contribution statistics. -type StatsService struct { - config *ConfigService - stats *Stats - mu sync.RWMutex -} - -// Stats contains all tracked statistics. -type Stats struct { - // Issue stats - IssuesAttempted int `json:"issuesAttempted"` - IssuesCompleted int `json:"issuesCompleted"` - IssuesSkipped int `json:"issuesSkipped"` - - // PR stats - PRsSubmitted int `json:"prsSubmitted"` - PRsMerged int `json:"prsMerged"` - PRsRejected int `json:"prsRejected"` - - // Repository stats - ReposContributed map[string]*RepoStats `json:"reposContributed"` - - // Streaks - CurrentStreak int `json:"currentStreak"` - LongestStreak int `json:"longestStreak"` - LastActivity time.Time `json:"lastActivity"` - - // Time tracking - TotalTimeSpent time.Duration `json:"totalTimeSpent"` - AverageTimePerPR time.Duration `json:"averageTimePerPR"` - - // Activity history (last 30 days) - DailyActivity map[string]*DayStats `json:"dailyActivity"` -} - -// RepoStats contains statistics for a single repository. -type RepoStats struct { - Name string `json:"name"` - IssuesFixed int `json:"issuesFixed"` - PRsSubmitted int `json:"prsSubmitted"` - PRsMerged int `json:"prsMerged"` - FirstContrib time.Time `json:"firstContrib"` - LastContrib time.Time `json:"lastContrib"` -} - -// DayStats contains statistics for a single day. -type DayStats struct { - Date string `json:"date"` - IssuesWorked int `json:"issuesWorked"` - PRsSubmitted int `json:"prsSubmitted"` - TimeSpent int `json:"timeSpentMinutes"` -} - -// NewStatsService creates a new StatsService. -func NewStatsService(config *ConfigService) *StatsService { - s := &StatsService{ - config: config, - stats: &Stats{ - ReposContributed: make(map[string]*RepoStats), - DailyActivity: make(map[string]*DayStats), - }, - } - s.load() - return s -} - -// ServiceName returns the service name for Wails. -func (s *StatsService) ServiceName() string { - return "StatsService" -} - -// GetStats returns a copy of the current statistics. -func (s *StatsService) GetStats() Stats { - s.mu.RLock() - defer s.mu.RUnlock() - return *s.stats -} - -// RecordIssueAttempted records that an issue was started. -func (s *StatsService) RecordIssueAttempted(repo string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.IssuesAttempted++ - s.ensureRepo(repo) - s.updateStreak() - s.updateDailyActivity("issue") - s.save() -} - -// RecordIssueCompleted records that an issue was completed. -func (s *StatsService) RecordIssueCompleted(repo string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.IssuesCompleted++ - if rs, ok := s.stats.ReposContributed[repo]; ok { - rs.IssuesFixed++ - rs.LastContrib = time.Now() - } - s.save() -} - -// RecordIssueSkipped records that an issue was skipped. -func (s *StatsService) RecordIssueSkipped() { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.IssuesSkipped++ - s.save() -} - -// RecordPRSubmitted records that a PR was submitted. -func (s *StatsService) RecordPRSubmitted(repo string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.PRsSubmitted++ - if rs, ok := s.stats.ReposContributed[repo]; ok { - rs.PRsSubmitted++ - rs.LastContrib = time.Now() - } - s.updateDailyActivity("pr") - s.save() -} - -// RecordPRMerged records that a PR was merged. -func (s *StatsService) RecordPRMerged(repo string) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.PRsMerged++ - if rs, ok := s.stats.ReposContributed[repo]; ok { - rs.PRsMerged++ - } - s.save() -} - -// RecordPRRejected records that a PR was rejected. -func (s *StatsService) RecordPRRejected() { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.PRsRejected++ - s.save() -} - -// RecordTimeSpent adds time spent on an issue. -func (s *StatsService) RecordTimeSpent(duration time.Duration) { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats.TotalTimeSpent += duration - - // Recalculate average - if s.stats.PRsSubmitted > 0 { - s.stats.AverageTimePerPR = s.stats.TotalTimeSpent / time.Duration(s.stats.PRsSubmitted) - } - - // Update daily activity - today := time.Now().Format("2006-01-02") - if day, ok := s.stats.DailyActivity[today]; ok { - day.TimeSpent += int(duration.Minutes()) - } - - s.save() -} - -// GetRepoStats returns statistics for a specific repository. -func (s *StatsService) GetRepoStats(repo string) *RepoStats { - s.mu.RLock() - defer s.mu.RUnlock() - return s.stats.ReposContributed[repo] -} - -// GetTopRepos returns the top N repositories by contributions. -func (s *StatsService) GetTopRepos(n int) []*RepoStats { - s.mu.RLock() - defer s.mu.RUnlock() - - repos := make([]*RepoStats, 0, len(s.stats.ReposContributed)) - for _, rs := range s.stats.ReposContributed { - repos = append(repos, rs) - } - - // Sort by PRs merged (descending) - for i := 0; i < len(repos)-1; i++ { - for j := i + 1; j < len(repos); j++ { - if repos[j].PRsMerged > repos[i].PRsMerged { - repos[i], repos[j] = repos[j], repos[i] - } - } - } - - if n > len(repos) { - n = len(repos) - } - return repos[:n] -} - -// GetActivityHistory returns the activity for the last N days. -func (s *StatsService) GetActivityHistory(days int) []*DayStats { - s.mu.RLock() - defer s.mu.RUnlock() - - result := make([]*DayStats, 0, days) - now := time.Now() - - for i := 0; i < days; i++ { - date := now.AddDate(0, 0, -i).Format("2006-01-02") - if day, ok := s.stats.DailyActivity[date]; ok { - result = append(result, day) - } else { - result = append(result, &DayStats{Date: date}) - } - } - - return result -} - -// ensureRepo creates a repo stats entry if it doesn't exist. -func (s *StatsService) ensureRepo(repo string) { - if _, ok := s.stats.ReposContributed[repo]; !ok { - s.stats.ReposContributed[repo] = &RepoStats{ - Name: repo, - FirstContrib: time.Now(), - LastContrib: time.Now(), - } - } -} - -// updateStreak updates the contribution streak. -func (s *StatsService) updateStreak() { - now := time.Now() - lastActivity := s.stats.LastActivity - - if lastActivity.IsZero() { - s.stats.CurrentStreak = 1 - } else { - daysSince := int(now.Sub(lastActivity).Hours() / 24) - if daysSince <= 1 { - // Same day or next day - if daysSince == 1 || now.Day() != lastActivity.Day() { - s.stats.CurrentStreak++ - } - } else { - // Streak broken - s.stats.CurrentStreak = 1 - } - } - - if s.stats.CurrentStreak > s.stats.LongestStreak { - s.stats.LongestStreak = s.stats.CurrentStreak - } - - s.stats.LastActivity = now -} - -// updateDailyActivity updates today's activity. -func (s *StatsService) updateDailyActivity(activityType string) { - today := time.Now().Format("2006-01-02") - - if _, ok := s.stats.DailyActivity[today]; !ok { - s.stats.DailyActivity[today] = &DayStats{Date: today} - } - - day := s.stats.DailyActivity[today] - switch activityType { - case "issue": - day.IssuesWorked++ - case "pr": - day.PRsSubmitted++ - } - - // Clean up old entries (keep last 90 days) - cutoff := time.Now().AddDate(0, 0, -90).Format("2006-01-02") - for date := range s.stats.DailyActivity { - if date < cutoff { - delete(s.stats.DailyActivity, date) - } - } -} - -// save persists stats to disk. -func (s *StatsService) save() { - dataDir := s.config.GetDataDir() - if dataDir == "" { - return - } - - path := filepath.Join(dataDir, "stats.json") - data, err := json.MarshalIndent(s.stats, "", " ") - if err != nil { - log.Printf("Failed to marshal stats: %v", err) - return - } - - if err := os.WriteFile(path, data, 0644); err != nil { - log.Printf("Failed to save stats: %v", err) - } -} - -// load restores stats from disk. -func (s *StatsService) load() { - dataDir := s.config.GetDataDir() - if dataDir == "" { - return - } - - path := filepath.Join(dataDir, "stats.json") - data, err := os.ReadFile(path) - if err != nil { - if !os.IsNotExist(err) { - log.Printf("Failed to read stats: %v", err) - } - return - } - - var stats Stats - if err := json.Unmarshal(data, &stats); err != nil { - log.Printf("Failed to unmarshal stats: %v", err) - return - } - - // Ensure maps are initialized - if stats.ReposContributed == nil { - stats.ReposContributed = make(map[string]*RepoStats) - } - if stats.DailyActivity == nil { - stats.DailyActivity = make(map[string]*DayStats) - } - - s.stats = &stats -} - -// Reset clears all statistics. -func (s *StatsService) Reset() error { - s.mu.Lock() - defer s.mu.Unlock() - - s.stats = &Stats{ - ReposContributed: make(map[string]*RepoStats), - DailyActivity: make(map[string]*DayStats), - } - s.save() - return nil -} diff --git a/internal/bugseti/submit.go b/internal/bugseti/submit.go deleted file mode 100644 index 1b4feca1..00000000 --- a/internal/bugseti/submit.go +++ /dev/null @@ -1,366 +0,0 @@ -// Package bugseti provides services for the BugSETI distributed bug fixing application. -package bugseti - -import ( - "bytes" - "context" - "fmt" - "log" - "os/exec" - "strings" - "time" - - forgejo "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2" - - "forge.lthn.ai/core/go/pkg/forge" -) - -// SubmitService handles the PR submission flow. -type SubmitService struct { - config *ConfigService - notify *NotifyService - stats *StatsService - forge *forge.Client -} - -// NewSubmitService creates a new SubmitService. -func NewSubmitService(config *ConfigService, notify *NotifyService, stats *StatsService, forgeClient *forge.Client) *SubmitService { - return &SubmitService{ - config: config, - notify: notify, - stats: stats, - forge: forgeClient, - } -} - -// ServiceName returns the service name for Wails. -func (s *SubmitService) ServiceName() string { - return "SubmitService" -} - -// PRSubmission contains the data for a pull request submission. -type PRSubmission struct { - Issue *Issue `json:"issue"` - Title string `json:"title"` - Body string `json:"body"` - Branch string `json:"branch"` - CommitMsg string `json:"commitMsg"` - Files []string `json:"files"` - WorkDir string `json:"workDir"` -} - -// PRResult contains the result of a PR submission. -type PRResult struct { - Success bool `json:"success"` - PRURL string `json:"prUrl,omitempty"` - PRNumber int `json:"prNumber,omitempty"` - Error string `json:"error,omitempty"` - ForkOwner string `json:"forkOwner,omitempty"` -} - -// Submit creates a pull request for the given issue. -// Flow: Fork -> Branch -> Commit -> Push -> PR -func (s *SubmitService) Submit(submission *PRSubmission) (*PRResult, error) { - if submission == nil || submission.Issue == nil { - return nil, fmt.Errorf("invalid submission") - } - - issue := submission.Issue - workDir := submission.WorkDir - if workDir == "" { - return nil, fmt.Errorf("work directory not specified") - } - - guard := getEthicsGuardWithRoot(context.Background(), s.config.GetMarketplaceMCPRoot()) - issueTitle := guard.SanitizeTitle(issue.Title) - - owner, repoName, err := splitRepo(issue.Repo) - if err != nil { - return &PRResult{Success: false, Error: err.Error()}, err - } - - // Step 1: Ensure we have a fork - forkOwner, err := s.ensureFork(owner, repoName) - if err != nil { - return &PRResult{Success: false, Error: fmt.Sprintf("fork failed: %v", err)}, err - } - - // Step 2: Create branch - branch := submission.Branch - if branch == "" { - branch = fmt.Sprintf("bugseti/issue-%d", issue.Number) - } - if err := s.createBranch(workDir, branch); err != nil { - return &PRResult{Success: false, Error: fmt.Sprintf("branch creation failed: %v", err)}, err - } - - // Step 3: Stage and commit changes - commitMsg := submission.CommitMsg - if commitMsg == "" { - commitMsg = fmt.Sprintf("fix: resolve issue #%d\n\n%s\n\nFixes #%d", issue.Number, issueTitle, issue.Number) - } else { - commitMsg = guard.SanitizeBody(commitMsg) - } - if err := s.commitChanges(workDir, submission.Files, commitMsg); err != nil { - return &PRResult{Success: false, Error: fmt.Sprintf("commit failed: %v", err)}, err - } - - // Step 4: Push to fork - if err := s.pushToFork(workDir, forkOwner, repoName, branch); err != nil { - return &PRResult{Success: false, Error: fmt.Sprintf("push failed: %v", err)}, err - } - - // Step 5: Create PR - prTitle := submission.Title - if prTitle == "" { - prTitle = fmt.Sprintf("Fix #%d: %s", issue.Number, issueTitle) - } else { - prTitle = guard.SanitizeTitle(prTitle) - } - prBody := submission.Body - if prBody == "" { - prBody = s.generatePRBody(issue) - } - prBody = guard.SanitizeBody(prBody) - - prURL, prNumber, err := s.createPR(owner, repoName, forkOwner, branch, prTitle, prBody) - if err != nil { - return &PRResult{Success: false, Error: fmt.Sprintf("PR creation failed: %v", err)}, err - } - - // Update stats - s.stats.RecordPRSubmitted(issue.Repo) - - // Notify user - s.notify.Notify("BugSETI", fmt.Sprintf("PR #%d submitted for issue #%d", prNumber, issue.Number)) - - return &PRResult{ - Success: true, - PRURL: prURL, - PRNumber: prNumber, - ForkOwner: forkOwner, - }, nil -} - -// ensureFork ensures a fork exists for the repo, returns the fork owner's username. -func (s *SubmitService) ensureFork(owner, repo string) (string, error) { - // Get current user - user, err := s.forge.GetCurrentUser() - if err != nil { - return "", fmt.Errorf("failed to get current user: %w", err) - } - username := user.UserName - - // Check if fork already exists - _, err = s.forge.GetRepo(username, repo) - if err == nil { - return username, nil - } - - // Fork doesn't exist, create it - log.Printf("Creating fork of %s/%s...", owner, repo) - _, err = s.forge.ForkRepo(owner, repo, "") - if err != nil { - return "", fmt.Errorf("failed to create fork: %w", err) - } - - // Wait for Forgejo to process the fork - time.Sleep(2 * time.Second) - - return username, nil -} - -// createBranch creates a new branch in the repository. -func (s *SubmitService) createBranch(workDir, branch string) error { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - // Fetch latest from upstream - cmd := exec.CommandContext(ctx, "git", "fetch", "origin") - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - log.Printf("WARNING: git fetch origin failed in %s: %v (proceeding with potentially stale data)", workDir, err) - } - - // Create and checkout new branch - cmd = exec.CommandContext(ctx, "git", "checkout", "-b", branch) - cmd.Dir = workDir - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - // Branch might already exist, try to checkout - cmd = exec.CommandContext(ctx, "git", "checkout", branch) - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to create/checkout branch: %s: %w", stderr.String(), err) - } - } - - return nil -} - -// commitChanges stages and commits the specified files. -func (s *SubmitService) commitChanges(workDir string, files []string, message string) error { - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - // Stage files - if len(files) == 0 { - // Stage all changes - cmd := exec.CommandContext(ctx, "git", "add", "-A") - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to stage changes: %w", err) - } - } else { - // Stage specific files - args := append([]string{"add"}, files...) - cmd := exec.CommandContext(ctx, "git", args...) - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to stage files: %w", err) - } - } - - // Check if there are changes to commit - cmd := exec.CommandContext(ctx, "git", "diff", "--cached", "--quiet") - cmd.Dir = workDir - if err := cmd.Run(); err == nil { - return fmt.Errorf("no changes to commit") - } - - // Commit - cmd = exec.CommandContext(ctx, "git", "commit", "-m", message) - cmd.Dir = workDir - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to commit: %s: %w", stderr.String(), err) - } - - return nil -} - -// pushToFork pushes the branch to the user's fork. -func (s *SubmitService) pushToFork(workDir, forkOwner, repoName, branch string) error { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) - defer cancel() - - // Add fork as remote if not exists - forkRemote := "fork" - cmd := exec.CommandContext(ctx, "git", "remote", "get-url", forkRemote) - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - // Construct fork URL using the forge instance URL - forkURL := fmt.Sprintf("%s/%s/%s.git", strings.TrimRight(s.forge.URL(), "/"), forkOwner, repoName) - - // Embed token for HTTPS push auth - if s.forge.Token() != "" { - forkURL = strings.Replace(forkURL, "://", fmt.Sprintf("://bugseti:%s@", s.forge.Token()), 1) - } - - cmd = exec.CommandContext(ctx, "git", "remote", "add", forkRemote, forkURL) - cmd.Dir = workDir - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to add fork remote: %w", err) - } - } - - // Push to fork - cmd = exec.CommandContext(ctx, "git", "push", "-u", forkRemote, branch) - cmd.Dir = workDir - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to push: %s: %w", stderr.String(), err) - } - - return nil -} - -// createPR creates a pull request using the Forgejo API. -func (s *SubmitService) createPR(owner, repo, forkOwner, branch, title, body string) (string, int, error) { - pr, err := s.forge.CreatePullRequest(owner, repo, forgejo.CreatePullRequestOption{ - Head: fmt.Sprintf("%s:%s", forkOwner, branch), - Base: "main", - Title: title, - Body: body, - }) - if err != nil { - return "", 0, fmt.Errorf("failed to create PR: %w", err) - } - - return pr.HTMLURL, int(pr.Index), nil -} - -// generatePRBody creates a default PR body for an issue. -func (s *SubmitService) generatePRBody(issue *Issue) string { - var body strings.Builder - - body.WriteString("## Summary\n\n") - body.WriteString(fmt.Sprintf("This PR addresses issue #%d.\n\n", issue.Number)) - - if issue.Context != nil && issue.Context.Summary != "" { - body.WriteString("## Context\n\n") - body.WriteString(issue.Context.Summary) - body.WriteString("\n\n") - } - - body.WriteString("## Changes\n\n") - body.WriteString("\n\n") - - body.WriteString("## Testing\n\n") - body.WriteString("\n\n") - - body.WriteString("---\n\n") - body.WriteString("*Submitted via [BugSETI](https://forge.lthn.ai/core/cli) - Distributed Bug Fixing*\n") - - return body.String() -} - -// GetPRStatus checks the status of a submitted PR. -func (s *SubmitService) GetPRStatus(repo string, prNumber int) (*PRStatus, error) { - owner, repoName, err := splitRepo(repo) - if err != nil { - return nil, err - } - - pr, err := s.forge.GetPullRequest(owner, repoName, int64(prNumber)) - if err != nil { - return nil, fmt.Errorf("failed to get PR status: %w", err) - } - - status := &PRStatus{ - State: string(pr.State), - Mergeable: pr.Mergeable, - } - - // Check CI status via combined commit status - if pr.Head != nil { - combined, err := s.forge.GetCombinedStatus(owner, repoName, pr.Head.Sha) - if err == nil && combined != nil { - status.CIPassing = combined.State == forgejo.StatusSuccess - } - } - - // Check review status - reviews, err := s.forge.ListPRReviews(owner, repoName, int64(prNumber)) - if err == nil { - for _, review := range reviews { - if review.State == forgejo.ReviewStateApproved { - status.Approved = true - break - } - } - } - - return status, nil -} - -// PRStatus represents the current status of a PR. -type PRStatus struct { - State string `json:"state"` - Mergeable bool `json:"mergeable"` - CIPassing bool `json:"ciPassing"` - Approved bool `json:"approved"` -} diff --git a/internal/bugseti/submit_test.go b/internal/bugseti/submit_test.go deleted file mode 100644 index 80a3999f..00000000 --- a/internal/bugseti/submit_test.go +++ /dev/null @@ -1,234 +0,0 @@ -package bugseti - -import ( - "strings" - "testing" -) - -func testSubmitService(t *testing.T) *SubmitService { - t.Helper() - cfg := testConfigService(t, nil, nil) - notify := &NotifyService{enabled: false, config: cfg} - stats := &StatsService{ - config: cfg, - stats: &Stats{ - ReposContributed: make(map[string]*RepoStats), - DailyActivity: make(map[string]*DayStats), - }, - } - return NewSubmitService(cfg, notify, stats, nil) -} - -// --- NewSubmitService / ServiceName --- - -func TestNewSubmitService_Good(t *testing.T) { - s := testSubmitService(t) - if s == nil { - t.Fatal("expected non-nil SubmitService") - } - if s.config == nil || s.notify == nil || s.stats == nil { - t.Fatal("expected all dependencies set") - } -} - -func TestServiceName_Good(t *testing.T) { - s := testSubmitService(t) - if got := s.ServiceName(); got != "SubmitService" { - t.Fatalf("expected %q, got %q", "SubmitService", got) - } -} - -// --- Submit validation --- - -func TestSubmit_Bad_NilSubmission(t *testing.T) { - s := testSubmitService(t) - _, err := s.Submit(nil) - if err == nil { - t.Fatal("expected error for nil submission") - } - if !strings.Contains(err.Error(), "invalid submission") { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestSubmit_Bad_NilIssue(t *testing.T) { - s := testSubmitService(t) - _, err := s.Submit(&PRSubmission{Issue: nil}) - if err == nil { - t.Fatal("expected error for nil issue") - } - if !strings.Contains(err.Error(), "invalid submission") { - t.Fatalf("unexpected error: %v", err) - } -} - -func TestSubmit_Bad_EmptyWorkDir(t *testing.T) { - s := testSubmitService(t) - _, err := s.Submit(&PRSubmission{ - Issue: &Issue{Number: 1, Repo: "owner/repo", Title: "test"}, - WorkDir: "", - }) - if err == nil { - t.Fatal("expected error for empty work directory") - } - if !strings.Contains(err.Error(), "work directory not specified") { - t.Fatalf("unexpected error: %v", err) - } -} - -// --- generatePRBody --- - -func TestGeneratePRBody_Good_Basic(t *testing.T) { - s := testSubmitService(t) - issue := &Issue{Number: 42, Repo: "owner/repo", Title: "A bug"} - body := s.generatePRBody(issue) - - if !strings.Contains(body, "#42") { - t.Fatal("PR body should reference issue number") - } - if !strings.Contains(body, "## Summary") { - t.Fatal("PR body should have Summary section") - } - if !strings.Contains(body, "## Changes") { - t.Fatal("PR body should have Changes section") - } - if !strings.Contains(body, "## Testing") { - t.Fatal("PR body should have Testing section") - } - if !strings.Contains(body, "BugSETI") { - t.Fatal("PR body should have BugSETI attribution") - } -} - -func TestGeneratePRBody_Good_WithContext(t *testing.T) { - s := testSubmitService(t) - issue := &Issue{ - Number: 7, - Repo: "owner/repo", - Title: "Fix login", - Context: &IssueContext{ - Summary: "The login endpoint returns 500 on empty password.", - }, - } - body := s.generatePRBody(issue) - - if !strings.Contains(body, "## Context") { - t.Fatal("PR body should have Context section when context exists") - } - if !strings.Contains(body, "login endpoint returns 500") { - t.Fatal("PR body should include context summary") - } -} - -func TestGeneratePRBody_Good_WithoutContext(t *testing.T) { - s := testSubmitService(t) - issue := &Issue{Number: 7, Repo: "owner/repo", Title: "Fix login"} - body := s.generatePRBody(issue) - - if strings.Contains(body, "## Context") { - t.Fatal("PR body should omit Context section when no context") - } -} - -func TestGeneratePRBody_Good_EmptyContextSummary(t *testing.T) { - s := testSubmitService(t) - issue := &Issue{ - Number: 7, - Repo: "owner/repo", - Title: "Fix login", - Context: &IssueContext{Summary: ""}, - } - body := s.generatePRBody(issue) - - if strings.Contains(body, "## Context") { - t.Fatal("PR body should omit Context section when summary is empty") - } -} - -// --- PRSubmission / PRResult struct tests --- - -func TestPRSubmission_Good_Defaults(t *testing.T) { - sub := &PRSubmission{ - Issue: &Issue{Number: 10, Repo: "o/r"}, - WorkDir: "/tmp/work", - } - if sub.Branch != "" { - t.Fatal("expected empty branch to be default") - } - if sub.Title != "" { - t.Fatal("expected empty title to be default") - } - if sub.CommitMsg != "" { - t.Fatal("expected empty commit msg to be default") - } -} - -func TestPRResult_Good_Success(t *testing.T) { - r := &PRResult{ - Success: true, - PRURL: "https://forge.lthn.ai/o/r/pulls/1", - PRNumber: 1, - ForkOwner: "me", - } - if !r.Success { - t.Fatal("expected success") - } - if r.Error != "" { - t.Fatal("expected no error on success") - } -} - -func TestPRResult_Good_Failure(t *testing.T) { - r := &PRResult{ - Success: false, - Error: "fork failed: something", - } - if r.Success { - t.Fatal("expected failure") - } - if r.Error == "" { - t.Fatal("expected error message") - } -} - -// --- PRStatus struct --- - -func TestPRStatus_Good(t *testing.T) { - s := &PRStatus{ - State: "open", - Mergeable: true, - CIPassing: true, - Approved: false, - } - if s.State != "open" { - t.Fatalf("expected open, got %s", s.State) - } - if !s.Mergeable { - t.Fatal("expected mergeable") - } - if s.Approved { - t.Fatal("expected not approved") - } -} - -// --- splitRepo --- - -func TestSplitRepo_Good(t *testing.T) { - owner, repo, err := splitRepo("myorg/myrepo") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - if owner != "myorg" || repo != "myrepo" { - t.Fatalf("expected myorg/myrepo, got %s/%s", owner, repo) - } -} - -func TestSplitRepo_Bad(t *testing.T) { - _, _, err := splitRepo("invalidrepo") - if err == nil { - t.Fatal("expected error for invalid repo format") - } - if !strings.Contains(err.Error(), "invalid repo format") { - t.Fatalf("unexpected error: %v", err) - } -} diff --git a/internal/bugseti/updater/channels.go b/internal/bugseti/updater/channels.go deleted file mode 100644 index 79ec4a82..00000000 --- a/internal/bugseti/updater/channels.go +++ /dev/null @@ -1,176 +0,0 @@ -// Package updater provides auto-update functionality for BugSETI. -package updater - -import ( - "fmt" - "regexp" - "strings" -) - -// Channel represents an update channel. -type Channel string - -const ( - // ChannelStable is the production release channel. - // Tags: bugseti-vX.Y.Z (e.g., bugseti-v1.0.0) - ChannelStable Channel = "stable" - - // ChannelBeta is the pre-release testing channel. - // Tags: bugseti-vX.Y.Z-beta.N (e.g., bugseti-v1.0.0-beta.1) - ChannelBeta Channel = "beta" - - // ChannelNightly is the latest development builds channel. - // Tags: bugseti-nightly-YYYYMMDD (e.g., bugseti-nightly-20260205) - ChannelNightly Channel = "nightly" -) - -// String returns the string representation of the channel. -func (c Channel) String() string { - return string(c) -} - -// DisplayName returns a human-readable name for the channel. -func (c Channel) DisplayName() string { - switch c { - case ChannelStable: - return "Stable" - case ChannelBeta: - return "Beta" - case ChannelNightly: - return "Nightly" - default: - return "Unknown" - } -} - -// Description returns a description of the channel. -func (c Channel) Description() string { - switch c { - case ChannelStable: - return "Production releases - most stable, recommended for most users" - case ChannelBeta: - return "Pre-release builds - new features being tested before stable release" - case ChannelNightly: - return "Latest development builds - bleeding edge, may be unstable" - default: - return "Unknown channel" - } -} - -// TagPrefix returns the tag prefix used for this channel. -func (c Channel) TagPrefix() string { - switch c { - case ChannelStable: - return "bugseti-v" - case ChannelBeta: - return "bugseti-v" - case ChannelNightly: - return "bugseti-nightly-" - default: - return "" - } -} - -// TagPattern returns a regex pattern to match tags for this channel. -func (c Channel) TagPattern() *regexp.Regexp { - switch c { - case ChannelStable: - // Match bugseti-vX.Y.Z but NOT bugseti-vX.Y.Z-beta.N - return regexp.MustCompile(`^bugseti-v(\d+\.\d+\.\d+)$`) - case ChannelBeta: - // Match bugseti-vX.Y.Z-beta.N - return regexp.MustCompile(`^bugseti-v(\d+\.\d+\.\d+-beta\.\d+)$`) - case ChannelNightly: - // Match bugseti-nightly-YYYYMMDD - return regexp.MustCompile(`^bugseti-nightly-(\d{8})$`) - default: - return nil - } -} - -// MatchesTag returns true if the given tag matches this channel's pattern. -func (c Channel) MatchesTag(tag string) bool { - pattern := c.TagPattern() - if pattern == nil { - return false - } - return pattern.MatchString(tag) -} - -// ExtractVersion extracts the version from a tag for this channel. -func (c Channel) ExtractVersion(tag string) string { - pattern := c.TagPattern() - if pattern == nil { - return "" - } - matches := pattern.FindStringSubmatch(tag) - if len(matches) < 2 { - return "" - } - return matches[1] -} - -// AllChannels returns all available channels. -func AllChannels() []Channel { - return []Channel{ChannelStable, ChannelBeta, ChannelNightly} -} - -// ParseChannel parses a string into a Channel. -func ParseChannel(s string) (Channel, error) { - switch strings.ToLower(s) { - case "stable": - return ChannelStable, nil - case "beta": - return ChannelBeta, nil - case "nightly": - return ChannelNightly, nil - default: - return "", fmt.Errorf("unknown channel: %s", s) - } -} - -// ChannelInfo contains information about an update channel. -type ChannelInfo struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` -} - -// GetChannelInfo returns information about a channel. -func GetChannelInfo(c Channel) ChannelInfo { - return ChannelInfo{ - ID: c.String(), - Name: c.DisplayName(), - Description: c.Description(), - } -} - -// GetAllChannelInfo returns information about all channels. -func GetAllChannelInfo() []ChannelInfo { - channels := AllChannels() - info := make([]ChannelInfo, len(channels)) - for i, c := range channels { - info[i] = GetChannelInfo(c) - } - return info -} - -// IncludesPrerelease returns true if the channel includes pre-release versions. -func (c Channel) IncludesPrerelease() bool { - return c == ChannelBeta || c == ChannelNightly -} - -// IncludesChannel returns true if this channel should include releases from the given channel. -// For example, beta channel includes stable releases, nightly includes both. -func (c Channel) IncludesChannel(other Channel) bool { - switch c { - case ChannelStable: - return other == ChannelStable - case ChannelBeta: - return other == ChannelStable || other == ChannelBeta - case ChannelNightly: - return true // Nightly users can see all releases - default: - return false - } -} diff --git a/internal/bugseti/updater/checker.go b/internal/bugseti/updater/checker.go deleted file mode 100644 index 368cb9e3..00000000 --- a/internal/bugseti/updater/checker.go +++ /dev/null @@ -1,379 +0,0 @@ -// Package updater provides auto-update functionality for BugSETI. -package updater - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "runtime" - "sort" - "strings" - "time" - - "golang.org/x/mod/semver" -) - -const ( - // GitHubReleasesAPI is the GitHub API endpoint for releases. - GitHubReleasesAPI = "https://api.github.com/repos/%s/%s/releases" - - // DefaultOwner is the default GitHub repository owner. - DefaultOwner = "host-uk" - - // DefaultRepo is the default GitHub repository name. - DefaultRepo = "core" - - // DefaultCheckInterval is the default interval between update checks. - DefaultCheckInterval = 6 * time.Hour -) - -// GitHubRelease represents a GitHub release from the API. -type GitHubRelease struct { - TagName string `json:"tag_name"` - Name string `json:"name"` - Body string `json:"body"` - Draft bool `json:"draft"` - Prerelease bool `json:"prerelease"` - PublishedAt time.Time `json:"published_at"` - Assets []GitHubAsset `json:"assets"` - HTMLURL string `json:"html_url"` -} - -// GitHubAsset represents a release asset from the GitHub API. -type GitHubAsset struct { - Name string `json:"name"` - Size int64 `json:"size"` - BrowserDownloadURL string `json:"browser_download_url"` - ContentType string `json:"content_type"` -} - -// ReleaseInfo contains information about an available release. -type ReleaseInfo struct { - Version string `json:"version"` - Channel Channel `json:"channel"` - Tag string `json:"tag"` - Name string `json:"name"` - Body string `json:"body"` - PublishedAt time.Time `json:"publishedAt"` - HTMLURL string `json:"htmlUrl"` - BinaryURL string `json:"binaryUrl"` - ArchiveURL string `json:"archiveUrl"` - ChecksumURL string `json:"checksumUrl"` - Size int64 `json:"size"` -} - -// UpdateCheckResult contains the result of an update check. -type UpdateCheckResult struct { - Available bool `json:"available"` - CurrentVersion string `json:"currentVersion"` - LatestVersion string `json:"latestVersion"` - Release *ReleaseInfo `json:"release,omitempty"` - Error string `json:"error,omitempty"` - CheckedAt time.Time `json:"checkedAt"` -} - -// Checker checks for available updates. -type Checker struct { - owner string - repo string - httpClient *http.Client -} - -// NewChecker creates a new update checker. -func NewChecker() *Checker { - return &Checker{ - owner: DefaultOwner, - repo: DefaultRepo, - httpClient: &http.Client{ - Timeout: 30 * time.Second, - }, - } -} - -// CheckForUpdate checks if a newer version is available. -func (c *Checker) CheckForUpdate(ctx context.Context, currentVersion string, channel Channel) (*UpdateCheckResult, error) { - result := &UpdateCheckResult{ - CurrentVersion: currentVersion, - CheckedAt: time.Now(), - } - - // Fetch releases from GitHub - releases, err := c.fetchReleases(ctx) - if err != nil { - result.Error = err.Error() - return result, err - } - - // Find the latest release for the channel - latest := c.findLatestRelease(releases, channel) - if latest == nil { - result.LatestVersion = currentVersion - return result, nil - } - - result.LatestVersion = latest.Version - result.Release = latest - - // Compare versions - if c.isNewerVersion(currentVersion, latest.Version, channel) { - result.Available = true - } - - return result, nil -} - -// fetchReleases fetches all releases from GitHub. -func (c *Checker) fetchReleases(ctx context.Context) ([]GitHubRelease, error) { - url := fmt.Sprintf(GitHubReleasesAPI, c.owner, c.repo) - - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - req.Header.Set("Accept", "application/vnd.github.v3+json") - req.Header.Set("User-Agent", "BugSETI-Updater") - - resp, err := c.httpClient.Do(req) - if err != nil { - return nil, fmt.Errorf("failed to fetch releases: %w", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("GitHub API returned status %d", resp.StatusCode) - } - - var releases []GitHubRelease - if err := json.NewDecoder(resp.Body).Decode(&releases); err != nil { - return nil, fmt.Errorf("failed to decode releases: %w", err) - } - - return releases, nil -} - -// findLatestRelease finds the latest release for the given channel. -func (c *Checker) findLatestRelease(releases []GitHubRelease, channel Channel) *ReleaseInfo { - var candidates []ReleaseInfo - - for _, release := range releases { - // Skip drafts - if release.Draft { - continue - } - - // Check if the tag matches our BugSETI release pattern - if !strings.HasPrefix(release.TagName, "bugseti-") { - continue - } - - // Determine the channel for this release - releaseChannel := c.determineChannel(release.TagName) - if releaseChannel == "" { - continue - } - - // Check if this release should be considered for the requested channel - if !channel.IncludesChannel(releaseChannel) { - continue - } - - // Extract version - version := releaseChannel.ExtractVersion(release.TagName) - if version == "" { - continue - } - - // Find the appropriate asset for this platform - binaryName := c.getBinaryName() - archiveName := c.getArchiveName() - checksumName := archiveName + ".sha256" - - var binaryURL, archiveURL, checksumURL string - var size int64 - - for _, asset := range release.Assets { - switch asset.Name { - case binaryName: - binaryURL = asset.BrowserDownloadURL - size = asset.Size - case archiveName: - archiveURL = asset.BrowserDownloadURL - if size == 0 { - size = asset.Size - } - case checksumName: - checksumURL = asset.BrowserDownloadURL - } - } - - // Skip if no binary available for this platform - if binaryURL == "" && archiveURL == "" { - continue - } - - candidates = append(candidates, ReleaseInfo{ - Version: version, - Channel: releaseChannel, - Tag: release.TagName, - Name: release.Name, - Body: release.Body, - PublishedAt: release.PublishedAt, - HTMLURL: release.HTMLURL, - BinaryURL: binaryURL, - ArchiveURL: archiveURL, - ChecksumURL: checksumURL, - Size: size, - }) - } - - if len(candidates) == 0 { - return nil - } - - // Sort by version (newest first) - sort.Slice(candidates, func(i, j int) bool { - return c.compareVersions(candidates[i].Version, candidates[j].Version, channel) > 0 - }) - - return &candidates[0] -} - -// determineChannel determines the channel from a release tag. -func (c *Checker) determineChannel(tag string) Channel { - for _, ch := range AllChannels() { - if ch.MatchesTag(tag) { - return ch - } - } - return "" -} - -// getBinaryName returns the binary name for the current platform. -func (c *Checker) getBinaryName() string { - ext := "" - if runtime.GOOS == "windows" { - ext = ".exe" - } - return fmt.Sprintf("bugseti-%s-%s%s", runtime.GOOS, runtime.GOARCH, ext) -} - -// getArchiveName returns the archive name for the current platform. -func (c *Checker) getArchiveName() string { - ext := "tar.gz" - if runtime.GOOS == "windows" { - ext = "zip" - } - return fmt.Sprintf("bugseti-%s-%s.%s", runtime.GOOS, runtime.GOARCH, ext) -} - -// isNewerVersion returns true if newVersion is newer than currentVersion. -func (c *Checker) isNewerVersion(currentVersion, newVersion string, channel Channel) bool { - // Handle nightly versions (date-based) - if channel == ChannelNightly { - return newVersion > currentVersion - } - - // Handle dev builds - if currentVersion == "dev" { - return true - } - - // Use semver comparison - current := c.normalizeSemver(currentVersion) - new := c.normalizeSemver(newVersion) - - return semver.Compare(new, current) > 0 -} - -// compareVersions compares two versions. -func (c *Checker) compareVersions(v1, v2 string, channel Channel) int { - // Handle nightly versions (date-based) - if channel == ChannelNightly { - if v1 > v2 { - return 1 - } else if v1 < v2 { - return -1 - } - return 0 - } - - // Use semver comparison - return semver.Compare(c.normalizeSemver(v1), c.normalizeSemver(v2)) -} - -// normalizeSemver ensures a version string has the 'v' prefix for semver. -func (c *Checker) normalizeSemver(version string) string { - if !strings.HasPrefix(version, "v") { - return "v" + version - } - return version -} - -// GetAllReleases returns all BugSETI releases from GitHub. -func (c *Checker) GetAllReleases(ctx context.Context) ([]ReleaseInfo, error) { - releases, err := c.fetchReleases(ctx) - if err != nil { - return nil, err - } - - var result []ReleaseInfo - for _, release := range releases { - if release.Draft { - continue - } - - if !strings.HasPrefix(release.TagName, "bugseti-") { - continue - } - - releaseChannel := c.determineChannel(release.TagName) - if releaseChannel == "" { - continue - } - - version := releaseChannel.ExtractVersion(release.TagName) - if version == "" { - continue - } - - binaryName := c.getBinaryName() - archiveName := c.getArchiveName() - checksumName := archiveName + ".sha256" - - var binaryURL, archiveURL, checksumURL string - var size int64 - - for _, asset := range release.Assets { - switch asset.Name { - case binaryName: - binaryURL = asset.BrowserDownloadURL - size = asset.Size - case archiveName: - archiveURL = asset.BrowserDownloadURL - if size == 0 { - size = asset.Size - } - case checksumName: - checksumURL = asset.BrowserDownloadURL - } - } - - result = append(result, ReleaseInfo{ - Version: version, - Channel: releaseChannel, - Tag: release.TagName, - Name: release.Name, - Body: release.Body, - PublishedAt: release.PublishedAt, - HTMLURL: release.HTMLURL, - BinaryURL: binaryURL, - ArchiveURL: archiveURL, - ChecksumURL: checksumURL, - Size: size, - }) - } - - return result, nil -} diff --git a/internal/bugseti/updater/download.go b/internal/bugseti/updater/download.go deleted file mode 100644 index 2ce6120b..00000000 --- a/internal/bugseti/updater/download.go +++ /dev/null @@ -1,427 +0,0 @@ -// Package updater provides auto-update functionality for BugSETI. -package updater - -import ( - "archive/tar" - "archive/zip" - "compress/gzip" - "context" - "crypto/sha256" - "encoding/hex" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "runtime" - "strings" -) - -// DownloadProgress reports download progress. -type DownloadProgress struct { - BytesDownloaded int64 `json:"bytesDownloaded"` - TotalBytes int64 `json:"totalBytes"` - Percent float64 `json:"percent"` -} - -// DownloadResult contains the result of a download operation. -type DownloadResult struct { - BinaryPath string `json:"binaryPath"` - Version string `json:"version"` - Checksum string `json:"checksum"` - VerifiedOK bool `json:"verifiedOK"` -} - -// Downloader handles downloading and verifying updates. -type Downloader struct { - httpClient *http.Client - stagingDir string - onProgress func(DownloadProgress) -} - -// NewDownloader creates a new update downloader. -func NewDownloader() (*Downloader, error) { - // Create staging directory in user's temp dir - stagingDir := filepath.Join(os.TempDir(), "bugseti-updates") - if err := os.MkdirAll(stagingDir, 0755); err != nil { - return nil, fmt.Errorf("failed to create staging directory: %w", err) - } - - return &Downloader{ - httpClient: &http.Client{}, - stagingDir: stagingDir, - }, nil -} - -// SetProgressCallback sets a callback for download progress updates. -func (d *Downloader) SetProgressCallback(cb func(DownloadProgress)) { - d.onProgress = cb -} - -// Download downloads a release and stages it for installation. -func (d *Downloader) Download(ctx context.Context, release *ReleaseInfo) (*DownloadResult, error) { - result := &DownloadResult{ - Version: release.Version, - } - - // Prefer archive download for extraction - downloadURL := release.ArchiveURL - if downloadURL == "" { - downloadURL = release.BinaryURL - } - if downloadURL == "" { - return nil, fmt.Errorf("no download URL available for release %s", release.Version) - } - - // Download the checksum first if available - var expectedChecksum string - if release.ChecksumURL != "" { - checksum, err := d.downloadChecksum(ctx, release.ChecksumURL) - if err != nil { - // Log but don't fail - checksum verification is optional - fmt.Printf("Warning: could not download checksum: %v\n", err) - } else { - expectedChecksum = checksum - } - } - - // Download the file - downloadedPath, err := d.downloadFile(ctx, downloadURL, release.Size) - if err != nil { - return nil, fmt.Errorf("failed to download update: %w", err) - } - - // Verify checksum if available - actualChecksum, err := d.calculateChecksum(downloadedPath) - if err != nil { - os.Remove(downloadedPath) - return nil, fmt.Errorf("failed to calculate checksum: %w", err) - } - result.Checksum = actualChecksum - - if expectedChecksum != "" { - if actualChecksum != expectedChecksum { - os.Remove(downloadedPath) - return nil, fmt.Errorf("checksum mismatch: expected %s, got %s", expectedChecksum, actualChecksum) - } - result.VerifiedOK = true - } - - // Extract if it's an archive - var binaryPath string - if strings.HasSuffix(downloadURL, ".tar.gz") { - binaryPath, err = d.extractTarGz(downloadedPath) - } else if strings.HasSuffix(downloadURL, ".zip") { - binaryPath, err = d.extractZip(downloadedPath) - } else { - // It's a raw binary - binaryPath = downloadedPath - } - - if err != nil { - os.Remove(downloadedPath) - return nil, fmt.Errorf("failed to extract archive: %w", err) - } - - // Make the binary executable (Unix only) - if runtime.GOOS != "windows" { - if err := os.Chmod(binaryPath, 0755); err != nil { - return nil, fmt.Errorf("failed to make binary executable: %w", err) - } - } - - result.BinaryPath = binaryPath - return result, nil -} - -// downloadChecksum downloads and parses a checksum file. -func (d *Downloader) downloadChecksum(ctx context.Context, url string) (string, error) { - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return "", err - } - req.Header.Set("User-Agent", "BugSETI-Updater") - - resp, err := d.httpClient.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("HTTP %d", resp.StatusCode) - } - - data, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - // Checksum file format: "hash filename" or just "hash" - parts := strings.Fields(strings.TrimSpace(string(data))) - if len(parts) == 0 { - return "", fmt.Errorf("empty checksum file") - } - - return parts[0], nil -} - -// downloadFile downloads a file with progress reporting. -func (d *Downloader) downloadFile(ctx context.Context, url string, expectedSize int64) (string, error) { - req, err := http.NewRequestWithContext(ctx, "GET", url, nil) - if err != nil { - return "", err - } - req.Header.Set("User-Agent", "BugSETI-Updater") - - resp, err := d.httpClient.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return "", fmt.Errorf("HTTP %d", resp.StatusCode) - } - - // Get total size from response or use expected size - totalSize := resp.ContentLength - if totalSize <= 0 { - totalSize = expectedSize - } - - // Create output file - filename := filepath.Base(url) - outPath := filepath.Join(d.stagingDir, filename) - out, err := os.Create(outPath) - if err != nil { - return "", err - } - defer out.Close() - - // Download with progress - var downloaded int64 - buf := make([]byte, 32*1024) // 32KB buffer - - for { - select { - case <-ctx.Done(): - os.Remove(outPath) - return "", ctx.Err() - default: - } - - n, readErr := resp.Body.Read(buf) - if n > 0 { - _, writeErr := out.Write(buf[:n]) - if writeErr != nil { - os.Remove(outPath) - return "", writeErr - } - downloaded += int64(n) - - // Report progress - if d.onProgress != nil && totalSize > 0 { - d.onProgress(DownloadProgress{ - BytesDownloaded: downloaded, - TotalBytes: totalSize, - Percent: float64(downloaded) / float64(totalSize) * 100, - }) - } - } - - if readErr == io.EOF { - break - } - if readErr != nil { - os.Remove(outPath) - return "", readErr - } - } - - return outPath, nil -} - -// calculateChecksum calculates the SHA256 checksum of a file. -func (d *Downloader) calculateChecksum(path string) (string, error) { - f, err := os.Open(path) - if err != nil { - return "", err - } - defer f.Close() - - h := sha256.New() - if _, err := io.Copy(h, f); err != nil { - return "", err - } - - return hex.EncodeToString(h.Sum(nil)), nil -} - -// extractTarGz extracts a .tar.gz archive and returns the path to the binary. -func (d *Downloader) extractTarGz(archivePath string) (string, error) { - f, err := os.Open(archivePath) - if err != nil { - return "", err - } - defer f.Close() - - gzr, err := gzip.NewReader(f) - if err != nil { - return "", err - } - defer gzr.Close() - - tr := tar.NewReader(gzr) - - extractDir := filepath.Join(d.stagingDir, "extracted") - os.RemoveAll(extractDir) - if err := os.MkdirAll(extractDir, 0755); err != nil { - return "", err - } - - var binaryPath string - binaryName := "bugseti" - if runtime.GOOS == "windows" { - binaryName = "bugseti.exe" - } - - for { - header, err := tr.Next() - if err == io.EOF { - break - } - if err != nil { - return "", err - } - - target := filepath.Join(extractDir, header.Name) - - // Prevent directory traversal - if !strings.HasPrefix(filepath.Clean(target), filepath.Clean(extractDir)) { - return "", fmt.Errorf("invalid file path in archive: %s", header.Name) - } - - switch header.Typeflag { - case tar.TypeDir: - if err := os.MkdirAll(target, 0755); err != nil { - return "", err - } - case tar.TypeReg: - // Create parent directory - if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { - return "", err - } - - outFile, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(header.Mode)) - if err != nil { - return "", err - } - - if _, err := io.Copy(outFile, tr); err != nil { - outFile.Close() - return "", err - } - outFile.Close() - - // Check if this is the binary we're looking for - if filepath.Base(header.Name) == binaryName { - binaryPath = target - } - } - } - - // Clean up archive - os.Remove(archivePath) - - if binaryPath == "" { - return "", fmt.Errorf("binary not found in archive") - } - - return binaryPath, nil -} - -// extractZip extracts a .zip archive and returns the path to the binary. -func (d *Downloader) extractZip(archivePath string) (string, error) { - r, err := zip.OpenReader(archivePath) - if err != nil { - return "", err - } - defer r.Close() - - extractDir := filepath.Join(d.stagingDir, "extracted") - os.RemoveAll(extractDir) - if err := os.MkdirAll(extractDir, 0755); err != nil { - return "", err - } - - var binaryPath string - binaryName := "bugseti" - if runtime.GOOS == "windows" { - binaryName = "bugseti.exe" - } - - for _, f := range r.File { - target := filepath.Join(extractDir, f.Name) - - // Prevent directory traversal - if !strings.HasPrefix(filepath.Clean(target), filepath.Clean(extractDir)) { - return "", fmt.Errorf("invalid file path in archive: %s", f.Name) - } - - if f.FileInfo().IsDir() { - if err := os.MkdirAll(target, 0755); err != nil { - return "", err - } - continue - } - - // Create parent directory - if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil { - return "", err - } - - rc, err := f.Open() - if err != nil { - return "", err - } - - outFile, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, f.Mode()) - if err != nil { - rc.Close() - return "", err - } - - _, err = io.Copy(outFile, rc) - rc.Close() - outFile.Close() - - if err != nil { - return "", err - } - - // Check if this is the binary we're looking for - if filepath.Base(f.Name) == binaryName { - binaryPath = target - } - } - - // Clean up archive - os.Remove(archivePath) - - if binaryPath == "" { - return "", fmt.Errorf("binary not found in archive") - } - - return binaryPath, nil -} - -// Cleanup removes all staged files. -func (d *Downloader) Cleanup() error { - return os.RemoveAll(d.stagingDir) -} - -// GetStagingDir returns the staging directory path. -func (d *Downloader) GetStagingDir() string { - return d.stagingDir -} diff --git a/internal/bugseti/updater/go.mod b/internal/bugseti/updater/go.mod deleted file mode 100644 index 5af27f0d..00000000 --- a/internal/bugseti/updater/go.mod +++ /dev/null @@ -1,30 +0,0 @@ -module forge.lthn.ai/core/cli/internal/bugseti/updater - -go 1.25.5 - -require ( - forge.lthn.ai/core/cli/internal/bugseti v0.0.0 - golang.org/x/mod v0.32.0 -) - -require ( - codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 // indirect - github.com/42wim/httpsig v1.2.3 // indirect - github.com/bahlo/generic-list-go v0.2.0 // indirect - github.com/buger/jsonparser v1.1.1 // indirect - github.com/davidmz/go-pageant v1.0.2 // indirect - github.com/go-fed/httpsig v1.1.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/go-version v1.7.0 // indirect - github.com/invopop/jsonschema v0.13.0 // indirect - github.com/mailru/easyjson v0.9.1 // indirect - github.com/mark3labs/mcp-go v0.43.2 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/sys v0.40.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) - -replace forge.lthn.ai/core/cli/internal/bugseti => ../ diff --git a/internal/bugseti/updater/go.sum b/internal/bugseti/updater/go.sum deleted file mode 100644 index 481c06a1..00000000 --- a/internal/bugseti/updater/go.sum +++ /dev/null @@ -1,28 +0,0 @@ -codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v2 v2.2.0 h1:HTCWpzyWQOHDWt3LzI6/d2jvUDsw/vgGRWm/8BTvcqI= -github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= -github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= -github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= -github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8= -github.com/mark3labs/mcp-go v0.43.2 h1:21PUSlWWiSbUPQwXIJ5WKlETixpFpq+WBpbMGDSVy/I= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= -github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/bugseti/updater/install.go b/internal/bugseti/updater/install.go deleted file mode 100644 index a443fa9b..00000000 --- a/internal/bugseti/updater/install.go +++ /dev/null @@ -1,284 +0,0 @@ -// Package updater provides auto-update functionality for BugSETI. -package updater - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "syscall" -) - -// InstallResult contains the result of an installation. -type InstallResult struct { - Success bool `json:"success"` - OldPath string `json:"oldPath"` - NewPath string `json:"newPath"` - BackupPath string `json:"backupPath"` - RestartNeeded bool `json:"restartNeeded"` - Error string `json:"error,omitempty"` -} - -// Installer handles installing updates and restarting the application. -type Installer struct { - executablePath string -} - -// NewInstaller creates a new installer. -func NewInstaller() (*Installer, error) { - execPath, err := os.Executable() - if err != nil { - return nil, fmt.Errorf("failed to get executable path: %w", err) - } - - // Resolve symlinks to get the real path - execPath, err = filepath.EvalSymlinks(execPath) - if err != nil { - return nil, fmt.Errorf("failed to resolve executable path: %w", err) - } - - return &Installer{ - executablePath: execPath, - }, nil -} - -// Install replaces the current binary with the new one. -func (i *Installer) Install(newBinaryPath string) (*InstallResult, error) { - result := &InstallResult{ - OldPath: i.executablePath, - NewPath: newBinaryPath, - RestartNeeded: true, - } - - // Verify the new binary exists and is executable - if _, err := os.Stat(newBinaryPath); err != nil { - result.Error = fmt.Sprintf("new binary not found: %v", err) - return result, fmt.Errorf("new binary not found: %w", err) - } - - // Create backup of current binary - backupPath := i.executablePath + ".bak" - result.BackupPath = backupPath - - // Platform-specific installation - var err error - switch runtime.GOOS { - case "windows": - err = i.installWindows(newBinaryPath, backupPath) - default: - err = i.installUnix(newBinaryPath, backupPath) - } - - if err != nil { - result.Error = err.Error() - return result, err - } - - result.Success = true - return result, nil -} - -// installUnix performs the installation on Unix-like systems. -func (i *Installer) installUnix(newBinaryPath, backupPath string) error { - // Remove old backup if exists - os.Remove(backupPath) - - // Rename current binary to backup - if err := os.Rename(i.executablePath, backupPath); err != nil { - return fmt.Errorf("failed to backup current binary: %w", err) - } - - // Copy new binary to target location - // We use copy instead of rename in case they're on different filesystems - if err := copyFile(newBinaryPath, i.executablePath); err != nil { - // Try to restore backup - os.Rename(backupPath, i.executablePath) - return fmt.Errorf("failed to install new binary: %w", err) - } - - // Make executable - if err := os.Chmod(i.executablePath, 0755); err != nil { - // Try to restore backup - os.Remove(i.executablePath) - os.Rename(backupPath, i.executablePath) - return fmt.Errorf("failed to make binary executable: %w", err) - } - - return nil -} - -// installWindows performs the installation on Windows. -// On Windows, we can't replace a running executable, so we use a different approach: -// 1. Rename current executable to .old -// 2. Copy new executable to target location -// 3. On next start, clean up the .old file -func (i *Installer) installWindows(newBinaryPath, backupPath string) error { - // Remove old backup if exists - os.Remove(backupPath) - - // On Windows, we can rename the running executable - if err := os.Rename(i.executablePath, backupPath); err != nil { - return fmt.Errorf("failed to backup current binary: %w", err) - } - - // Copy new binary to target location - if err := copyFile(newBinaryPath, i.executablePath); err != nil { - // Try to restore backup - os.Rename(backupPath, i.executablePath) - return fmt.Errorf("failed to install new binary: %w", err) - } - - return nil -} - -// Restart restarts the application with the new binary. -func (i *Installer) Restart() error { - args := os.Args - env := os.Environ() - - switch runtime.GOOS { - case "windows": - return i.restartWindows(args, env) - default: - return i.restartUnix(args, env) - } -} - -// restartUnix restarts the application on Unix-like systems using exec. -func (i *Installer) restartUnix(args []string, env []string) error { - // Use syscall.Exec to replace the current process - // This is the cleanest way to restart on Unix - return syscall.Exec(i.executablePath, args, env) -} - -// restartWindows restarts the application on Windows. -func (i *Installer) restartWindows(args []string, env []string) error { - // On Windows, we can't use exec to replace the process - // Instead, we start a new process and exit the current one - cmd := exec.Command(i.executablePath, args[1:]...) - cmd.Env = env - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = os.Stdin - - if err := cmd.Start(); err != nil { - return fmt.Errorf("failed to start new process: %w", err) - } - - // Exit current process - os.Exit(0) - return nil // Never reached -} - -// RestartLater schedules a restart for when the app next starts. -// This is useful when the user wants to continue working and restart later. -func (i *Installer) RestartLater() error { - // Create a marker file that indicates a restart is pending - markerPath := filepath.Join(filepath.Dir(i.executablePath), ".bugseti-restart-pending") - return os.WriteFile(markerPath, []byte("restart"), 0644) -} - -// CheckPendingRestart checks if a restart was scheduled. -func (i *Installer) CheckPendingRestart() bool { - markerPath := filepath.Join(filepath.Dir(i.executablePath), ".bugseti-restart-pending") - _, err := os.Stat(markerPath) - return err == nil -} - -// ClearPendingRestart clears the pending restart marker. -func (i *Installer) ClearPendingRestart() error { - markerPath := filepath.Join(filepath.Dir(i.executablePath), ".bugseti-restart-pending") - return os.Remove(markerPath) -} - -// CleanupBackup removes the backup binary after a successful update. -func (i *Installer) CleanupBackup() error { - backupPath := i.executablePath + ".bak" - if _, err := os.Stat(backupPath); err == nil { - return os.Remove(backupPath) - } - return nil -} - -// Rollback restores the previous version from backup. -func (i *Installer) Rollback() error { - backupPath := i.executablePath + ".bak" - - // Check if backup exists - if _, err := os.Stat(backupPath); err != nil { - return fmt.Errorf("backup not found: %w", err) - } - - // Remove current binary - if err := os.Remove(i.executablePath); err != nil { - return fmt.Errorf("failed to remove current binary: %w", err) - } - - // Restore backup - if err := os.Rename(backupPath, i.executablePath); err != nil { - return fmt.Errorf("failed to restore backup: %w", err) - } - - return nil -} - -// GetExecutablePath returns the path to the current executable. -func (i *Installer) GetExecutablePath() string { - return i.executablePath -} - -// copyFile copies a file from src to dst. -func copyFile(src, dst string) error { - sourceFile, err := os.Open(src) - if err != nil { - return err - } - defer sourceFile.Close() - - // Get source file info for permissions - sourceInfo, err := sourceFile.Stat() - if err != nil { - return err - } - - destFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, sourceInfo.Mode()) - if err != nil { - return err - } - defer destFile.Close() - - _, err = destFile.ReadFrom(sourceFile) - return err -} - -// CanSelfUpdate checks if the application has permission to update itself. -func CanSelfUpdate() bool { - execPath, err := os.Executable() - if err != nil { - return false - } - - execPath, err = filepath.EvalSymlinks(execPath) - if err != nil { - return false - } - - // Check if we can write to the executable's directory - dir := filepath.Dir(execPath) - testFile := filepath.Join(dir, ".bugseti-update-test") - - f, err := os.Create(testFile) - if err != nil { - return false - } - f.Close() - os.Remove(testFile) - - return true -} - -// NeedsElevation returns true if the update requires elevated privileges. -func NeedsElevation() bool { - return !CanSelfUpdate() -} diff --git a/internal/bugseti/updater/service.go b/internal/bugseti/updater/service.go deleted file mode 100644 index 54c60510..00000000 --- a/internal/bugseti/updater/service.go +++ /dev/null @@ -1,322 +0,0 @@ -// Package updater provides auto-update functionality for BugSETI. -package updater - -import ( - "context" - "log" - "sync" - "time" - - "forge.lthn.ai/core/cli/internal/bugseti" -) - -// Service provides update functionality and Wails bindings. -type Service struct { - config *bugseti.ConfigService - checker *Checker - downloader *Downloader - installer *Installer - - mu sync.RWMutex - lastResult *UpdateCheckResult - pendingUpdate *DownloadResult - - // Background check - stopCh chan struct{} - running bool -} - -// NewService creates a new update service. -func NewService(config *bugseti.ConfigService) (*Service, error) { - downloader, err := NewDownloader() - if err != nil { - return nil, err - } - - installer, err := NewInstaller() - if err != nil { - return nil, err - } - - return &Service{ - config: config, - checker: NewChecker(), - downloader: downloader, - installer: installer, - }, nil -} - -// ServiceName returns the service name for Wails. -func (s *Service) ServiceName() string { - return "UpdateService" -} - -// Start begins the background update checker. -func (s *Service) Start() { - s.mu.Lock() - if s.running { - s.mu.Unlock() - return - } - s.running = true - s.stopCh = make(chan struct{}) - s.mu.Unlock() - - go s.runBackgroundChecker() -} - -// Stop stops the background update checker. -func (s *Service) Stop() { - s.mu.Lock() - defer s.mu.Unlock() - - if !s.running { - return - } - - s.running = false - close(s.stopCh) -} - -// runBackgroundChecker runs periodic update checks. -func (s *Service) runBackgroundChecker() { - // Initial check after a short delay - time.Sleep(30 * time.Second) - - for { - select { - case <-s.stopCh: - return - default: - } - - if s.config.ShouldCheckForUpdates() { - log.Println("Checking for updates...") - _, err := s.CheckForUpdate() - if err != nil { - log.Printf("Update check failed: %v", err) - } - } - - // Check interval from config (minimum 1 hour) - interval := time.Duration(s.config.GetUpdateCheckInterval()) * time.Hour - if interval < time.Hour { - interval = time.Hour - } - - select { - case <-s.stopCh: - return - case <-time.After(interval): - } - } -} - -// GetSettings returns the update settings. -func (s *Service) GetSettings() bugseti.UpdateSettings { - return s.config.GetUpdateSettings() -} - -// SetSettings updates the update settings. -func (s *Service) SetSettings(settings bugseti.UpdateSettings) error { - return s.config.SetUpdateSettings(settings) -} - -// GetVersionInfo returns the current version information. -func (s *Service) GetVersionInfo() bugseti.VersionInfo { - return bugseti.GetVersionInfo() -} - -// GetChannels returns all available update channels. -func (s *Service) GetChannels() []ChannelInfo { - return GetAllChannelInfo() -} - -// CheckForUpdate checks if an update is available. -func (s *Service) CheckForUpdate() (*UpdateCheckResult, error) { - currentVersion := bugseti.GetVersion() - channelStr := s.config.GetUpdateChannel() - - channel, err := ParseChannel(channelStr) - if err != nil { - channel = ChannelStable - } - - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - - result, err := s.checker.CheckForUpdate(ctx, currentVersion, channel) - if err != nil { - return result, err - } - - // Update last check time - s.config.SetLastUpdateCheck(time.Now()) - - // Store result - s.mu.Lock() - s.lastResult = result - s.mu.Unlock() - - // If auto-update is enabled and an update is available, download it - if result.Available && s.config.IsAutoUpdateEnabled() { - go s.downloadUpdate(result.Release) - } - - return result, nil -} - -// GetLastCheckResult returns the last update check result. -func (s *Service) GetLastCheckResult() *UpdateCheckResult { - s.mu.RLock() - defer s.mu.RUnlock() - return s.lastResult -} - -// downloadUpdate downloads an update in the background. -func (s *Service) downloadUpdate(release *ReleaseInfo) { - if release == nil { - return - } - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - log.Printf("Downloading update %s...", release.Version) - - result, err := s.downloader.Download(ctx, release) - if err != nil { - log.Printf("Failed to download update: %v", err) - return - } - - log.Printf("Update %s downloaded and staged at %s", release.Version, result.BinaryPath) - - s.mu.Lock() - s.pendingUpdate = result - s.mu.Unlock() -} - -// DownloadUpdate downloads the latest available update. -func (s *Service) DownloadUpdate() (*DownloadResult, error) { - s.mu.RLock() - lastResult := s.lastResult - s.mu.RUnlock() - - if lastResult == nil || !lastResult.Available || lastResult.Release == nil { - // Need to check first - result, err := s.CheckForUpdate() - if err != nil { - return nil, err - } - if !result.Available { - return nil, nil - } - lastResult = result - } - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - defer cancel() - - downloadResult, err := s.downloader.Download(ctx, lastResult.Release) - if err != nil { - return nil, err - } - - s.mu.Lock() - s.pendingUpdate = downloadResult - s.mu.Unlock() - - return downloadResult, nil -} - -// InstallUpdate installs a previously downloaded update. -func (s *Service) InstallUpdate() (*InstallResult, error) { - s.mu.RLock() - pending := s.pendingUpdate - s.mu.RUnlock() - - if pending == nil { - // Try to download first - downloadResult, err := s.DownloadUpdate() - if err != nil { - return nil, err - } - if downloadResult == nil { - return &InstallResult{ - Success: false, - Error: "No update available", - }, nil - } - pending = downloadResult - } - - result, err := s.installer.Install(pending.BinaryPath) - if err != nil { - return result, err - } - - // Clear pending update - s.mu.Lock() - s.pendingUpdate = nil - s.mu.Unlock() - - return result, nil -} - -// InstallAndRestart installs the update and restarts the application. -func (s *Service) InstallAndRestart() error { - result, err := s.InstallUpdate() - if err != nil { - return err - } - - if !result.Success { - return nil - } - - return s.installer.Restart() -} - -// HasPendingUpdate returns true if there's a downloaded update ready to install. -func (s *Service) HasPendingUpdate() bool { - s.mu.RLock() - defer s.mu.RUnlock() - return s.pendingUpdate != nil -} - -// GetPendingUpdate returns information about the pending update. -func (s *Service) GetPendingUpdate() *DownloadResult { - s.mu.RLock() - defer s.mu.RUnlock() - return s.pendingUpdate -} - -// CancelPendingUpdate cancels and removes the pending update. -func (s *Service) CancelPendingUpdate() error { - s.mu.Lock() - defer s.mu.Unlock() - - s.pendingUpdate = nil - return s.downloader.Cleanup() -} - -// CanSelfUpdate returns true if the application can update itself. -func (s *Service) CanSelfUpdate() bool { - return CanSelfUpdate() -} - -// NeedsElevation returns true if the update requires elevated privileges. -func (s *Service) NeedsElevation() bool { - return NeedsElevation() -} - -// Rollback restores the previous version. -func (s *Service) Rollback() error { - return s.installer.Rollback() -} - -// CleanupAfterUpdate cleans up backup files after a successful update. -func (s *Service) CleanupAfterUpdate() error { - return s.installer.CleanupBackup() -} diff --git a/internal/bugseti/version.go b/internal/bugseti/version.go deleted file mode 100644 index 506425c5..00000000 --- a/internal/bugseti/version.go +++ /dev/null @@ -1,122 +0,0 @@ -// Package bugseti provides version information for the BugSETI application. -package bugseti - -import ( - "fmt" - "runtime" -) - -// Version information - these are set at build time via ldflags -// Example: go build -ldflags "-X forge.lthn.ai/core/cli/internal/bugseti.Version=1.0.0" -var ( - // Version is the semantic version (e.g., "1.0.0", "1.0.0-beta.1", "nightly-20260205") - Version = "dev" - - // Channel is the release channel (stable, beta, nightly) - Channel = "dev" - - // Commit is the git commit SHA - Commit = "unknown" - - // BuildTime is the UTC build timestamp - BuildTime = "unknown" -) - -// VersionInfo contains all version-related information. -type VersionInfo struct { - Version string `json:"version"` - Channel string `json:"channel"` - Commit string `json:"commit"` - BuildTime string `json:"buildTime"` - GoVersion string `json:"goVersion"` - OS string `json:"os"` - Arch string `json:"arch"` -} - -// GetVersion returns the current version string. -func GetVersion() string { - return Version -} - -// GetChannel returns the release channel. -func GetChannel() string { - return Channel -} - -// GetVersionInfo returns complete version information. -func GetVersionInfo() VersionInfo { - return VersionInfo{ - Version: Version, - Channel: Channel, - Commit: Commit, - BuildTime: BuildTime, - GoVersion: runtime.Version(), - OS: runtime.GOOS, - Arch: runtime.GOARCH, - } -} - -// GetVersionString returns a formatted version string for display. -func GetVersionString() string { - if Channel == "dev" { - return fmt.Sprintf("BugSETI %s (development build)", Version) - } - if Channel == "nightly" { - return fmt.Sprintf("BugSETI %s (nightly)", Version) - } - if Channel == "beta" { - return fmt.Sprintf("BugSETI v%s (beta)", Version) - } - return fmt.Sprintf("BugSETI v%s", Version) -} - -// GetShortCommit returns the first 7 characters of the commit hash. -func GetShortCommit() string { - if len(Commit) >= 7 { - return Commit[:7] - } - return Commit -} - -// IsDevelopment returns true if this is a development build. -func IsDevelopment() bool { - return Channel == "dev" || Version == "dev" -} - -// IsPrerelease returns true if this is a prerelease build (beta or nightly). -func IsPrerelease() bool { - return Channel == "beta" || Channel == "nightly" -} - -// VersionService provides version information to the frontend via Wails. -type VersionService struct{} - -// NewVersionService creates a new VersionService. -func NewVersionService() *VersionService { - return &VersionService{} -} - -// ServiceName returns the service name for Wails. -func (v *VersionService) ServiceName() string { - return "VersionService" -} - -// GetVersion returns the version string. -func (v *VersionService) GetVersion() string { - return GetVersion() -} - -// GetChannel returns the release channel. -func (v *VersionService) GetChannel() string { - return GetChannel() -} - -// GetVersionInfo returns complete version information. -func (v *VersionService) GetVersionInfo() VersionInfo { - return GetVersionInfo() -} - -// GetVersionString returns a formatted version string. -func (v *VersionService) GetVersionString() string { - return GetVersionString() -} diff --git a/internal/tools/i18n-validate/main.go b/internal/tools/i18n-validate/main.go deleted file mode 100644 index 5e0d942c..00000000 --- a/internal/tools/i18n-validate/main.go +++ /dev/null @@ -1,525 +0,0 @@ -// Command i18n-validate scans Go source files for i18n key usage and validates -// them against the locale JSON files. -// -// Usage: -// -// go run ./cmd/i18n-validate ./... -// go run ./cmd/i18n-validate ./pkg/cli ./cmd/dev -// -// The validator checks: -// - T("key") calls - validates key exists in locale files -// - C("intent", ...) calls - validates intent exists in registered intents -// - i18n.T("key") and i18n.C("intent", ...) qualified calls -// -// Exit codes: -// - 0: All keys valid -// - 1: Missing keys found -// - 2: Error during validation -package main - -import ( - "encoding/json" - "fmt" - "go/ast" - "go/parser" - "go/token" - "os" - "path/filepath" - "sort" - "strings" -) - -// KeyUsage records where a key is used in the source code. -type KeyUsage struct { - Key string - File string - Line int - Function string // "T" or "C" -} - -// ValidationResult holds the results of validation. -type ValidationResult struct { - TotalKeys int - ValidKeys int - MissingKeys []KeyUsage - IntentKeys int - MessageKeys int -} - -func main() { - if len(os.Args) < 2 { - fmt.Fprintln(os.Stderr, "Usage: i18n-validate ") - fmt.Fprintln(os.Stderr, "Example: i18n-validate ./...") - os.Exit(2) - } - - // Find the project root (where locales are) - root, err := findProjectRoot() - if err != nil { - fmt.Fprintf(os.Stderr, "Error finding project root: %v\n", err) - os.Exit(2) - } - - // Load valid keys from locale files - validKeys, err := loadValidKeys(filepath.Join(root, "pkg/i18n/locales")) - if err != nil { - fmt.Fprintf(os.Stderr, "Error loading locale files: %v\n", err) - os.Exit(2) - } - - // Load valid intents - validIntents := loadValidIntents() - - // Scan source files - usages, err := scanPackages(os.Args[1:]) - if err != nil { - fmt.Fprintf(os.Stderr, "Error scanning packages: %v\n", err) - os.Exit(2) - } - - // Validate - result := validate(usages, validKeys, validIntents) - - // Report - printReport(result) - - if len(result.MissingKeys) > 0 { - os.Exit(1) - } -} - -// findProjectRoot finds the project root by looking for go.mod. -func findProjectRoot() (string, error) { - dir, err := os.Getwd() - if err != nil { - return "", err - } - - for { - if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { - return dir, nil - } - parent := filepath.Dir(dir) - if parent == dir { - return "", fmt.Errorf("could not find go.mod in any parent directory") - } - dir = parent - } -} - -// loadValidKeys loads all valid keys from locale JSON files. -func loadValidKeys(localesDir string) (map[string]bool, error) { - keys := make(map[string]bool) - - entries, err := os.ReadDir(localesDir) - if err != nil { - return nil, fmt.Errorf("reading locales dir: %w", err) - } - - for _, entry := range entries { - if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".json") { - continue - } - - data, err := os.ReadFile(filepath.Join(localesDir, entry.Name())) - if err != nil { - return nil, fmt.Errorf("reading %s: %w", entry.Name(), err) - } - - var raw map[string]any - if err := json.Unmarshal(data, &raw); err != nil { - return nil, fmt.Errorf("parsing %s: %w", entry.Name(), err) - } - - extractKeys("", raw, keys) - } - - return keys, nil -} - -// extractKeys recursively extracts flattened keys from nested JSON. -func extractKeys(prefix string, data map[string]any, out map[string]bool) { - for key, value := range data { - fullKey := key - if prefix != "" { - fullKey = prefix + "." + key - } - - switch v := value.(type) { - case string: - out[fullKey] = true - case map[string]any: - // Check if it's a plural/verb/noun object (has specific keys) - if isPluralOrGrammarObject(v) { - out[fullKey] = true - } else { - extractKeys(fullKey, v, out) - } - } - } -} - -// isPluralOrGrammarObject checks if a map is a leaf object (plural forms, verb forms, etc). -func isPluralOrGrammarObject(m map[string]any) bool { - // CLDR plural keys - _, hasOne := m["one"] - _, hasOther := m["other"] - _, hasZero := m["zero"] - _, hasTwo := m["two"] - _, hasFew := m["few"] - _, hasMany := m["many"] - - // Grammar keys - _, hasPast := m["past"] - _, hasGerund := m["gerund"] - _, hasGender := m["gender"] - _, hasBase := m["base"] - - // Article keys - _, hasDefault := m["default"] - _, hasVowel := m["vowel"] - - if hasOne || hasOther || hasZero || hasTwo || hasFew || hasMany { - return true - } - if hasPast || hasGerund || hasGender || hasBase { - return true - } - if hasDefault || hasVowel { - return true - } - - return false -} - -// loadValidIntents returns the set of valid intent keys. -func loadValidIntents() map[string]bool { - // Core intents - these match what's defined in intents.go - return map[string]bool{ - // Destructive - "core.delete": true, - "core.remove": true, - "core.discard": true, - "core.reset": true, - "core.overwrite": true, - // Creation - "core.create": true, - "core.add": true, - "core.clone": true, - "core.copy": true, - // Modification - "core.save": true, - "core.update": true, - "core.rename": true, - "core.move": true, - // Git - "core.commit": true, - "core.push": true, - "core.pull": true, - "core.merge": true, - "core.rebase": true, - // Network - "core.install": true, - "core.download": true, - "core.upload": true, - "core.publish": true, - "core.deploy": true, - // Process - "core.start": true, - "core.stop": true, - "core.restart": true, - "core.run": true, - "core.build": true, - "core.test": true, - // Information - "core.continue": true, - "core.proceed": true, - "core.confirm": true, - // Additional - "core.sync": true, - "core.boot": true, - "core.format": true, - "core.analyse": true, - "core.link": true, - "core.unlink": true, - "core.fetch": true, - "core.generate": true, - "core.validate": true, - "core.check": true, - "core.scan": true, - } -} - -// scanPackages scans Go packages for i18n key usage. -func scanPackages(patterns []string) ([]KeyUsage, error) { - var usages []KeyUsage - - for _, pattern := range patterns { - // Expand pattern - matches, err := expandPattern(pattern) - if err != nil { - return nil, fmt.Errorf("expanding pattern %q: %w", pattern, err) - } - - for _, dir := range matches { - dirUsages, err := scanDirectory(dir) - if err != nil { - return nil, fmt.Errorf("scanning %s: %w", dir, err) - } - usages = append(usages, dirUsages...) - } - } - - return usages, nil -} - -// expandPattern expands a Go package pattern to directories. -func expandPattern(pattern string) ([]string, error) { - // Handle ./... or ... pattern - if strings.HasSuffix(pattern, "...") { - base := strings.TrimSuffix(pattern, "...") - base = strings.TrimSuffix(base, "/") - if base == "" || base == "." { - base = "." - } - return findAllGoDirs(base) - } - - // Single directory - return []string{pattern}, nil -} - -// findAllGoDirs finds all directories containing .go files. -func findAllGoDirs(root string) ([]string, error) { - var dirs []string - seen := make(map[string]bool) - - err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - if err != nil { - return nil // Continue walking even on error - } - - if info == nil { - return nil - } - - // Skip vendor, testdata, and hidden directories (but not . itself) - if info.IsDir() { - name := info.Name() - if name == "vendor" || name == "testdata" || (strings.HasPrefix(name, ".") && name != ".") { - return filepath.SkipDir - } - return nil - } - - // Check for .go files - if strings.HasSuffix(path, ".go") { - dir := filepath.Dir(path) - if !seen[dir] { - seen[dir] = true - dirs = append(dirs, dir) - } - } - - return nil - }) - - return dirs, err -} - -// scanDirectory scans a directory for i18n key usage. -func scanDirectory(dir string) ([]KeyUsage, error) { - var usages []KeyUsage - - fset := token.NewFileSet() - // Parse all .go files except those ending exactly in _test.go - pkgs, err := parser.ParseDir(fset, dir, func(fi os.FileInfo) bool { - name := fi.Name() - // Only exclude files that are actual test files (ending in _test.go) - // Files like "go_test_cmd.go" should be included - return strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go") - }, 0) - if err != nil { - return nil, err - } - - for _, pkg := range pkgs { - for filename, file := range pkg.Files { - fileUsages := scanFile(fset, filename, file) - usages = append(usages, fileUsages...) - } - } - - return usages, nil -} - -// scanFile scans a single file for i18n key usage. -func scanFile(fset *token.FileSet, filename string, file *ast.File) []KeyUsage { - var usages []KeyUsage - - ast.Inspect(file, func(n ast.Node) bool { - call, ok := n.(*ast.CallExpr) - if !ok { - return true - } - - funcName := getFuncName(call) - if funcName == "" { - return true - } - - // Check for T(), C(), i18n.T(), i18n.C() - switch funcName { - case "T", "i18n.T", "_", "i18n._": - if key := extractStringArg(call, 0); key != "" { - pos := fset.Position(call.Pos()) - usages = append(usages, KeyUsage{ - Key: key, - File: filename, - Line: pos.Line, - Function: "T", - }) - } - case "C", "i18n.C": - if key := extractStringArg(call, 0); key != "" { - pos := fset.Position(call.Pos()) - usages = append(usages, KeyUsage{ - Key: key, - File: filename, - Line: pos.Line, - Function: "C", - }) - } - case "I", "i18n.I": - if key := extractStringArg(call, 0); key != "" { - pos := fset.Position(call.Pos()) - usages = append(usages, KeyUsage{ - Key: key, - File: filename, - Line: pos.Line, - Function: "C", // I() is an intent builder - }) - } - } - - return true - }) - - return usages -} - -// getFuncName extracts the function name from a call expression. -func getFuncName(call *ast.CallExpr) string { - switch fn := call.Fun.(type) { - case *ast.Ident: - return fn.Name - case *ast.SelectorExpr: - if ident, ok := fn.X.(*ast.Ident); ok { - return ident.Name + "." + fn.Sel.Name - } - } - return "" -} - -// extractStringArg extracts a string literal from a call argument. -func extractStringArg(call *ast.CallExpr, index int) string { - if index >= len(call.Args) { - return "" - } - - arg := call.Args[index] - - // Direct string literal - if lit, ok := arg.(*ast.BasicLit); ok && lit.Kind == token.STRING { - // Remove quotes - s := lit.Value - if len(s) >= 2 { - return s[1 : len(s)-1] - } - } - - // Identifier (constant reference) - we skip these as they're type-safe - if _, ok := arg.(*ast.Ident); ok { - return "" // Skip constants like IntentCoreDelete - } - - // Selector (like i18n.IntentCoreDelete) - skip these too - if _, ok := arg.(*ast.SelectorExpr); ok { - return "" - } - - return "" -} - -// validate validates key usages against valid keys and intents. -func validate(usages []KeyUsage, validKeys, validIntents map[string]bool) ValidationResult { - result := ValidationResult{ - TotalKeys: len(usages), - } - - for _, usage := range usages { - if usage.Function == "C" { - result.IntentKeys++ - // Check intent keys - if validIntents[usage.Key] { - result.ValidKeys++ - } else { - // Also allow custom intents (non-core.* prefix) - if !strings.HasPrefix(usage.Key, "core.") { - result.ValidKeys++ // Assume custom intents are valid - } else { - result.MissingKeys = append(result.MissingKeys, usage) - } - } - } else { - result.MessageKeys++ - // Check message keys - if validKeys[usage.Key] { - result.ValidKeys++ - } else if strings.HasPrefix(usage.Key, "core.") { - // core.* keys used with T() are intent keys - if validIntents[usage.Key] { - result.ValidKeys++ - } else { - result.MissingKeys = append(result.MissingKeys, usage) - } - } else { - result.MissingKeys = append(result.MissingKeys, usage) - } - } - } - - return result -} - -// printReport prints the validation report. -func printReport(result ValidationResult) { - fmt.Printf("i18n Validation Report\n") - fmt.Printf("======================\n\n") - fmt.Printf("Total keys scanned: %d\n", result.TotalKeys) - fmt.Printf(" Message keys (T): %d\n", result.MessageKeys) - fmt.Printf(" Intent keys (C): %d\n", result.IntentKeys) - fmt.Printf("Valid keys: %d\n", result.ValidKeys) - fmt.Printf("Missing keys: %d\n", len(result.MissingKeys)) - - if len(result.MissingKeys) > 0 { - fmt.Printf("\nMissing Keys:\n") - fmt.Printf("-------------\n") - - // Sort by file then line - sort.Slice(result.MissingKeys, func(i, j int) bool { - if result.MissingKeys[i].File != result.MissingKeys[j].File { - return result.MissingKeys[i].File < result.MissingKeys[j].File - } - return result.MissingKeys[i].Line < result.MissingKeys[j].Line - }) - - for _, usage := range result.MissingKeys { - fmt.Printf(" %s:%d: %s(%q)\n", usage.File, usage.Line, usage.Function, usage.Key) - } - - fmt.Printf("\nAdd these keys to pkg/i18n/locales/en_GB.json or use constants from pkg/i18n/keys.go\n") - } else { - fmt.Printf("\nAll keys are valid!\n") - } -}